mirror of https://github.com/dahall/Vanara.git
135 lines
6.6 KiB
C#
135 lines
6.6 KiB
C#
|
using Microsoft.Win32;
|
|||
|
using System;
|
|||
|
using System.Collections.Generic;
|
|||
|
using static Vanara.PInvoke.ShlwApi;
|
|||
|
|
|||
|
namespace Vanara.Windows.Shell.Registration
|
|||
|
{
|
|||
|
/// <summary>Manages registry entries related to file types and file associations.</summary>
|
|||
|
public class FileTypeAssociation : RegBasedSettings
|
|||
|
{
|
|||
|
internal FileTypeAssociation(string ext, RegistryKey key, bool readOnly) : base(key, readOnly)
|
|||
|
{
|
|||
|
Extension = ext;
|
|||
|
OpenWithProgIds = new RegBasedKeyCollection(key.OpenSubKey("OpenWithProgIds", !readOnly), readOnly);
|
|||
|
}
|
|||
|
|
|||
|
/// <summary>Gets or sets the Content Type value to the file type's MIME content type.</summary>
|
|||
|
/// <value>The MIME content type.</value>
|
|||
|
public string ContentType
|
|||
|
{
|
|||
|
get => key.GetValue("ContentType")?.ToString();
|
|||
|
set => UpdateValue("ContentType", value);
|
|||
|
}
|
|||
|
|
|||
|
/// <summary>Gets or sets the default value of the extension subkey to the ProgID to which it is linked.</summary>
|
|||
|
/// <value>The default ProgID for this extension.</value>
|
|||
|
/// <exception cref="InvalidOperationException">The specified ProgId is not registered with the system.</exception>
|
|||
|
public string DefaultProgId
|
|||
|
{
|
|||
|
get => key.GetValue(null)?.ToString();
|
|||
|
set
|
|||
|
{
|
|||
|
if (!Registry.ClassesRoot.HasSubKey(value))
|
|||
|
throw new InvalidOperationException("The specified ProgId is not registered with the system.");
|
|||
|
var old = DefaultProgId;
|
|||
|
if (old != null) OpenWithProgIds.Add(old);
|
|||
|
UpdateValue(null, value);
|
|||
|
if (value != null) OpenWithProgIds.Add(value);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/// <summary>Gets the extension of this file association.</summary>
|
|||
|
/// <value>The extension.</value>
|
|||
|
public string Extension { get; }
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// Gets a list of alternate ProgIDs for this file type. The programs for these ProgIDs appear in the Open with menu and are
|
|||
|
/// available as default Windows Store apps for the file type. Whenever an application takes over this file type by changing the
|
|||
|
/// default value, it should also add an entry to this list.
|
|||
|
/// </summary>
|
|||
|
/// <value>The open with prog ids.</value>
|
|||
|
public ICollection<string> OpenWithProgIds { get; }
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// Gets or sets the PerceivedType to which the file belongs, if any. This value is not used by Windows versions prior to Windows
|
|||
|
/// Vista. For more information, see "Perceived Types and Application Registration".
|
|||
|
/// </summary>
|
|||
|
public PERCEIVED? PerceivedType
|
|||
|
{
|
|||
|
get
|
|||
|
{
|
|||
|
var value = key.GetValue("PerceivedType")?.ToString();
|
|||
|
return value is null ? null : (PERCEIVED?)(PERCEIVED)Enum.Parse(typeof(PERCEIVED), "PERCEIVED_TYPE_" + value.ToUpper());
|
|||
|
}
|
|||
|
set => UpdateValue("PerceivedType", value?.ToString().Substring(15).ToLower());
|
|||
|
}
|
|||
|
|
|||
|
//public string LongExtension;
|
|||
|
// .ext => ProgId => shellnew ??
|
|||
|
|
|||
|
/// <summary>Opens the specified extension for reading or editing.</summary>
|
|||
|
/// <param name="extension">The file extension to examine. This value must be in the format ".ext".</param>
|
|||
|
/// <param name="systemWide">
|
|||
|
/// If <see langword="true"/>, examine the file association system-wide. If <see langword="false"/>, examine the file association
|
|||
|
/// for the current user only.
|
|||
|
/// </param>
|
|||
|
/// <param name="readOnly">
|
|||
|
/// If <see langword="true"/>, provides read-only access to the registration; If <see langword="false"/>, the properties can be set
|
|||
|
/// to update the registration values.
|
|||
|
/// </param>
|
|||
|
/// <returns>The requested <see cref="FileTypeAssociation"/> instance.</returns>
|
|||
|
public static FileTypeAssociation Open(string extension, bool systemWide = false, bool readOnly = true)
|
|||
|
{
|
|||
|
var key = ShellRegistrar.GetRoot(systemWide, readOnly, extension ?? throw new ArgumentNullException(nameof(extension)));
|
|||
|
if (key is null) throw new ArgumentException("Unable to load specified extension", nameof(extension));
|
|||
|
return new FileTypeAssociation(extension, key, readOnly);
|
|||
|
}
|
|||
|
|
|||
|
/// <summary>Registers the specified files extension.</summary>
|
|||
|
/// <param name="extension">The file extension to register. This value must be in the format ".ext".</param>
|
|||
|
/// <param name="systemWide">
|
|||
|
/// If <see langword="true"/>, register the file association system-wide. If <see langword="false"/>, register the file association
|
|||
|
/// for the current user only.
|
|||
|
/// </param>
|
|||
|
/// <returns>A <see cref="FileTypeAssociation"/> instance to continue definition of file extension settings.</returns>
|
|||
|
public static FileTypeAssociation Register(string extension, bool systemWide = false)
|
|||
|
{
|
|||
|
if (extension is null) throw new ArgumentNullException(nameof(extension));
|
|||
|
if (!extension.StartsWith(".")) throw new ArgumentException("The value must be in the format \".ext\"", nameof(extension));
|
|||
|
var root = ShellRegistrar.GetRoot(systemWide, true, extension);
|
|||
|
return new FileTypeAssociation(extension, root, false);
|
|||
|
}
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// <para>Unregisters the file association.</para>
|
|||
|
/// <note type="warning">Removing a file association can break multiple applications since this will remove all ProgId associations.
|
|||
|
/// Do this with extreme caution and forethought. Consider just removing the ProgId for your application using <see cref="FileTypeAssociation.OpenWithProgIds"/>.</note>
|
|||
|
/// </summary>
|
|||
|
/// <param name="extension">The file extension to unregister. This value must be in the format ".ext".</param>
|
|||
|
/// <param name="systemWide">
|
|||
|
/// If <span class="keyword"><span class="languageSpecificText"><span class="cs">true</span><span class="vb">True</span><span
|
|||
|
/// class="cpp">true</span></span></span><span class="nu"><span class="keyword">true</span> ( <span class="keyword">True</span> in
|
|||
|
/// Visual Basic)</span>, unregister the file association system-wide. If <span class="keyword"><span
|
|||
|
/// class="languageSpecificText"><span class="cs">false</span><span class="vb">False</span><span
|
|||
|
/// class="cpp">false</span></span></span><span class="nu"><span class="keyword">false</span> ( <span class="keyword">False</span>
|
|||
|
/// in Visual Basic)</span>, unregister the file association for the current user only.
|
|||
|
/// </param>
|
|||
|
/// <exception cref="InvalidOperationException">Unable to find association key in the registry.</exception>
|
|||
|
public static void Unregister(string extension, bool systemWide = false)
|
|||
|
{
|
|||
|
if (extension is null) throw new ArgumentNullException(nameof(extension));
|
|||
|
if (!extension.StartsWith(".")) throw new ArgumentException("The value must be in the format \".ext\"", nameof(extension));
|
|||
|
using var sk = ShellRegistrar.GetRoot(systemWide, true);
|
|||
|
try { sk.DeleteSubKeyTree(extension); } catch { sk.DeleteSubKey(extension, false); }
|
|||
|
ShellRegistrar.NotifyShell();
|
|||
|
}
|
|||
|
|
|||
|
/// <inheritdoc/>
|
|||
|
public override void Dispose()
|
|||
|
{
|
|||
|
base.Dispose();
|
|||
|
ShellRegistrar.NotifyShell();
|
|||
|
}
|
|||
|
}
|
|||
|
}
|