/// <summary> /// Registers the server associations. /// </summary> /// <param name="serverClsid">The server CLSID.</param> /// <param name="serverType">Type of the server.</param> /// <param name="serverName">Name of the server.</param> /// <param name="associationAttributes">The association attributes.</param> /// <param name="registrationType">Type of the registration.</param> internal static void RegisterServerAssociations(Guid serverClsid, ServerType serverType, string serverName, IEnumerable<COMServerAssociationAttribute> associationAttributes, RegistrationType registrationType) { // Go through each association. foreach (var associationAttribute in associationAttributes) { // Get the assocation classes. var associationClassNames = CreateClassNamesForAssociations(associationAttribute.AssociationType, associationAttribute.Associations, registrationType); // Open the classes key. using (var classesKey = OpenClassesRoot(registrationType)) { // For each one, create the server type key. foreach (var associationClassName in associationClassNames) { // Create the server key. using (var serverKey = classesKey.CreateSubKey(GetKeyForServerType(associationClassName, serverType, serverName))) { // Set the server class id. if (serverKey != null) serverKey.SetValue(null, serverClsid.ToRegistryString()); } // If we're a shell icon handler, we must also set the defaulticon. if (serverType == ServerType.ShellIconHandler) SetIconHandlerDefaultIcon(classesKey, associationClassName); } } } }
/// <summary> /// Determines whether an extension is approved. /// </summary> /// <param name="serverClsid">The server CLSID.</param> /// <param name="registrationType">Type of the registration.</param> /// <returns> /// <c>true</c> if the extension is approved; otherwise, <c>false</c>. /// </returns> /// <exception cref="System.InvalidOperationException">Failed to open the Approved Extensions key.</exception> private static bool IsExtensionApproved(Guid serverClsid, RegistrationType registrationType) { // Open the approved extensions key. using (var approvedKey = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, registrationType == RegistrationType.OS64Bit ? RegistryView.Registry64 : RegistryView.Registry32) .OpenSubKey(@"Software\Microsoft\Windows\CurrentVersion\Shell Extensions\Approved", RegistryKeyPermissionCheck.ReadSubTree)) { // If we can't open the key, we're going to have problems. if (approvedKey == null) throw new InvalidOperationException("Failed to open the Approved Extensions key."); return approvedKey.GetValueNames().Any(vn => vn.Equals(serverClsid.ToRegistryString(), StringComparison.OrdinalIgnoreCase)); } }
/// <summary> /// Gets the server registration info. /// </summary> /// <param name="serverCLSID">The server CLSID.</param> /// <param name="registrationType">Type of the registration.</param> /// <returns> /// The ServerRegistrationInfo if the server is registered, otherwise false. /// </returns> public static ShellExtensionRegistrationInfo GetServerRegistrationInfo(Guid serverCLSID, RegistrationType registrationType) { // We can very quickly check to see if the server is approved. bool serverApproved = IsExtensionApproved(serverCLSID, registrationType); // Open the classes. using (var classesKey = OpenClassesKey(registrationType, RegistryKeyPermissionCheck.ReadSubTree)) { // Do we have a subkey for the server? using (var serverClassKey = classesKey.OpenSubKey(serverCLSID.ToRegistryString())) { // If there's no subkey, the server isn't registered. if (serverClassKey == null) return null; // Do we have an InProc32 server? using(var inproc32ServerKey = serverClassKey.OpenSubKey(KeyName_InProc32)) { // If we do, we can return the server info for an inproc 32 server. if (inproc32ServerKey != null) { // Get the default value. var defaultValue = GetValueOrEmpty(inproc32ServerKey, null); // If we default value is null or empty, we've got a partially registered server. if (string.IsNullOrEmpty(defaultValue)) return new ShellExtensionRegistrationInfo(ServerRegistationType.PartiallyRegistered, serverCLSID); // Get the threading model. var threadingModel = GetValueOrEmpty(inproc32ServerKey, KeyName_ThreadingModel); // Is it a .NET server? if (defaultValue == KeyValue_NetFrameworkServer) { // We've got a .NET server. We should have one subkey, with the assembly version. var subkeyName = inproc32ServerKey.GetSubKeyNames().FirstOrDefault(); // If we have no subkey name, we've got a partially registered server. if (subkeyName == null) return new ShellExtensionRegistrationInfo(ServerRegistationType.PartiallyRegistered, serverCLSID); // Otherwise we now have the assembly version. var assemblyVersion = subkeyName; // Open the assembly subkey. using (var assemblySubkey = inproc32ServerKey.OpenSubKey(assemblyVersion)) { // If we can't open the key, we've got a problem. if (assemblySubkey == null) throw new InvalidOperationException("Can't open the details of the server."); // Read the managed server details. var assembly = GetValueOrEmpty(assemblySubkey, KeyName_Assembly); var @class = GetValueOrEmpty(assemblySubkey, KeyName_Class); var runtimeVersion = GetValueOrEmpty(assemblySubkey, KeyName_RuntimeVersion); var codeBase = assemblySubkey.GetValue(KeyName_CodeBase, null); // Return the server info. return new ShellExtensionRegistrationInfo(ServerRegistationType.ManagedInProc32, serverCLSID) { ThreadingModel = threadingModel, Assembly = assembly, AssemblyVersion = assemblyVersion, Class = @class, RuntimeVersion = runtimeVersion, CodeBase = codeBase != null ? codeBase.ToString() : null, IsApproved = serverApproved }; } } // We've got a native COM server. // Return the server info. return new ShellExtensionRegistrationInfo(ServerRegistationType.NativeInProc32, serverCLSID) { ThreadingModel = threadingModel, ServerPath = defaultValue, IsApproved = serverApproved }; } } // If by this point we haven't return server info, we've got a partially registered server. return new ShellExtensionRegistrationInfo(ServerRegistationType.PartiallyRegistered, serverCLSID); } } }