mirror of https://github.com/dahall/Vanara.git
129 lines
6.5 KiB
C#
129 lines
6.5 KiB
C#
using Microsoft.Win32;
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Reflection;
|
|
using System.Runtime.InteropServices;
|
|
using Vanara.Windows.Shell.Registration;
|
|
using static Vanara.PInvoke.Shell32;
|
|
|
|
namespace Vanara.Windows.Shell
|
|
{
|
|
/// <summary>Contains static methods used to register and unregister shell items in the Windows Registry.</summary>
|
|
public static class ShellRegistrar
|
|
{
|
|
/// <summary>Gets a dictionary of registered applications in the current system.</summary>
|
|
/// <value>The dictionary of registered applications.</value>
|
|
public static IReadOnlyDictionary<string, AppRegistration> Applications { get; } = new AppDictionary(true);
|
|
|
|
/// <summary>Gets a dictionary of registered file type associations in the current system.</summary>
|
|
/// <value>The dictionary of file type associations.</value>
|
|
public static IReadOnlyDictionary<string, FileTypeAssociation> FileTypeAssociations { get; } = new FileTypeDictionary(true);
|
|
|
|
/// <summary>Gets a dictionary of registered ProgId's in the current system.</summary>
|
|
/// <value>The dictionary of ProgId values.</value>
|
|
public static IReadOnlyDictionary<string, ProgId> ProgIds { get; } = new ProgIdDictionary(true);
|
|
|
|
/// <summary>Gets a dictionary of registered shell associations in the current system.</summary>
|
|
/// <value>The dictionary of shell associations.</value>
|
|
public static IReadOnlyDictionary<string, ShellAssociation> ShellAssociations { get; } = new ShellAssociationDictionary(true);
|
|
|
|
/// <summary>Gets the CLSID for the specified type.</summary>
|
|
/// <param name="type">The type.</param>
|
|
/// <returns>The CLSID value for the type. Calls <see cref="Type.GUID"/> to get the value.</returns>
|
|
public static Guid CLSID(this Type type) => type.GUID;
|
|
|
|
/// <summary>Determines if the specified type is registered as a COM Local Server.</summary>
|
|
/// <typeparam name="TComObject">The type of the COM object.</typeparam>
|
|
/// <param name="assembly">
|
|
/// The assembly used to get the full path of the executable. If this value is <see langword="null"/>, then the assembly of
|
|
/// <typeparamref name="TComObject"/> will be used.
|
|
/// </param>
|
|
/// <param name="systemWide">
|
|
/// If set to <see langword="true"/>, registration is checked in HKLM; otherwise it is registered for the user only in HKCU.
|
|
/// </param>
|
|
/// <param name="appId">The AppId to relate to this CLSID. If <see langword="null"/>, the CLSID value will be used.</param>
|
|
public static bool IsRegisteredAsLocalServer<TComObject>(Assembly assembly = null, bool systemWide = false, Guid? appId = null) where TComObject : ComObject
|
|
{
|
|
var cmdLine = (assembly ?? typeof(TComObject).Assembly).Location;
|
|
var clsid = GetClsid<TComObject>();
|
|
var _appId = appId ?? clsid;
|
|
|
|
using (var root = GetRoot(systemWide, true))
|
|
{
|
|
if (!root.HasSubKey(@"CLSID\" + clsid.ToRegString())) return false;
|
|
using (var rClsid = root.OpenSubKey(@"CLSID\" + clsid.ToRegString() + @"\LocalServer32"))
|
|
if (rClsid == null || !string.Equals(rClsid.GetValue("")?.ToString(), cmdLine, StringComparison.OrdinalIgnoreCase)) return false;
|
|
if (!root.HasSubKey(@"AppID\" + _appId.ToRegString())) return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
#if NETFRAMEWORK
|
|
|
|
/// <summary>Registers the specified type as a COM Local Server.</summary>
|
|
/// <typeparam name="TComObject">The type of the COM object.</typeparam>
|
|
/// <param name="pszFriendlyName">The friendly name of the COM object.</param>
|
|
/// <param name="cmdLineArgs">The command line arguments to supply to the executable on startup.</param>
|
|
/// <param name="assembly">
|
|
/// The assembly used to get the full path of the executable. If this value is <see langword="null"/>, then the assembly of
|
|
/// <typeparamref name="TComObject"/> will be used.
|
|
/// </param>
|
|
/// <param name="systemWide">
|
|
/// If set to <see langword="true"/>, the COM object is registered system-wide in HKLM; otherwise it is registered for the user only
|
|
/// in HKCU.
|
|
/// </param>
|
|
/// <param name="appId">The AppId to relate to this CLSID. If <see langword="null"/>, the CLSID value will be used.</param>
|
|
public static void RegisterLocalServer<TComObject>(string pszFriendlyName, string cmdLineArgs = null, Assembly assembly = null, bool systemWide = false, Guid? appId = null) where TComObject : ComObject
|
|
{
|
|
if (assembly == null) assembly = typeof(TComObject).Assembly;
|
|
var cmdLine = assembly.Location;
|
|
var qCmdLine = string.Concat("\"", cmdLine, "\"");
|
|
var typelib = Marshal.GetTypeLibGuidForAssembly(assembly);
|
|
var clsid = GetClsid<TComObject>();
|
|
var _appId = appId ?? clsid;
|
|
if (!(cmdLineArgs is null)) qCmdLine += " " + cmdLineArgs;
|
|
|
|
using (var root = GetRoot(systemWide, true))
|
|
using (root.CreateSubKey(@"AppID\" + _appId.ToRegString(), pszFriendlyName))
|
|
using (var rClsid = root.CreateSubKey(@"CLSID\" + clsid.ToRegString(), pszFriendlyName))
|
|
using (rClsid.CreateSubKey("TypeLib", typelib.ToRegString()))
|
|
using (var rLS32 = rClsid.CreateSubKey("LocalServer32", cmdLineArgs is null ? qCmdLine : string.Concat("\"", qCmdLine, "\"")))
|
|
{
|
|
rClsid.SetValue("AppId", _appId.ToRegString());
|
|
rLS32.SetValue("ServerExecutable", cmdLine);
|
|
}
|
|
}
|
|
|
|
#endif
|
|
|
|
/// <summary>Unregisters the COM Local Server.</summary>
|
|
/// <typeparam name="TComObject">The type of the COM object.</typeparam>
|
|
/// <param name="systemWide">
|
|
/// If set to <see langword="true"/>, the COM object is unregistered system-wide from HKLM; otherwise it is unregistered for the
|
|
/// user only in HKCU.
|
|
/// </param>
|
|
/// <param name="appId">The AppId to relate to this CLSID. If <see langword="null"/>, the CLSID value will be used.</param>
|
|
public static void UnregisterLocalServer<TComObject>(bool systemWide = false, Guid? appId = null) where TComObject : ComObject
|
|
{
|
|
var clsid = GetClsid<TComObject>();
|
|
using (var root = GetRoot(systemWide, true))
|
|
{
|
|
root.DeleteSubKeyTree(@"AppID\" + (appId ?? clsid).ToRegString());
|
|
root.DeleteSubKeyTree(@"CLSID\" + clsid.ToRegString());
|
|
}
|
|
}
|
|
|
|
internal static RegistryKey GetRoot(bool systemWide = true, bool writable = false, string subkey = null)
|
|
{
|
|
if (!writable && subkey is null)
|
|
return Registry.ClassesRoot;
|
|
var key = systemWide ? Registry.LocalMachine : Registry.CurrentUser;
|
|
var fullsubkey = @"Software\Classes" + (subkey is null ? "" : "\\" + subkey);
|
|
return writable ? key.CreateSubKey(fullsubkey) : key.OpenSubKey(fullsubkey, writable);
|
|
}
|
|
|
|
internal static void NotifyShell() => SHChangeNotify(SHCNE.SHCNE_ASSOCCHANGED, SHCNF.SHCNF_FLUSHNOWAIT | SHCNF.SHCNF_IDLIST);
|
|
|
|
private static Guid GetClsid<TComObject>() => typeof(TComObject).CLSID();
|
|
}
|
|
} |