Code:
/ DotNET / DotNET / 8.0 / untmp / whidbey / REDBITS / ndp / clr / src / BCL / System / Runtime / InteropServices / RegistrationServices.cs / 1 / RegistrationServices.cs
// ==++== // // Copyright (c) Microsoft Corporation. All rights reserved. // // ==--== /*============================================================================== ** ** Class: RegistrationServices ** ** ** Purpose: This class provides services for registering and unregistering ** a managed server for use by COM. ** ** ** ** ** Change the way how to register and unregister a managed server ** =============================================================================*/ namespace System.Runtime.InteropServices { using System; using System.Collections; using System.IO; using System.Reflection; using System.Security; using System.Security.Permissions; using System.Text; using System.Threading; using Microsoft.Win32; using System.Runtime.CompilerServices; using System.Globalization; using System.Runtime.Versioning; [Flags] public enum RegistrationClassContext { InProcessServer = 0x1, InProcessHandler = 0x2, LocalServer = 0x4, InProcessServer16 = 0x8, RemoteServer = 0x10, InProcessHandler16 = 0x20, Reserved1 = 0x40, Reserved2 = 0x80, Reserved3 = 0x100, Reserved4 = 0x200, NoCodeDownload = 0x400, Reserved5 = 0x800, NoCustomMarshal = 0x1000, EnableCodeDownload = 0x2000, NoFailureLog = 0x4000, DisableActivateAsActivator = 0x8000, EnableActivateAsActivator = 0x10000, FromDefaultContext = 0x20000 } [Flags] public enum RegistrationConnectionType { SingleUse = 0, MultipleUse = 1, MultiSeparate = 2, Suspended = 4, Surrogate = 8, } [Guid("475E398F-8AFA-43a7-A3BE-F4EF8D6787C9")] [ClassInterface(ClassInterfaceType.None)] [System.Runtime.InteropServices.ComVisible(true)] public class RegistrationServices : IRegistrationServices { #region Constants private const String strManagedCategoryGuid = "{62C8FE65-4EBB-45e7-B440-6E39B2CDBF29}"; private const String strDocStringPrefix = ""; private const String strManagedTypeThreadingModel = "Both"; private const String strComponentCategorySubKey = "Component Categories"; private const String strManagedCategoryDescription = ".NET Category"; private const String strImplementedCategoriesSubKey = "Implemented Categories"; private const String strMsCorEEFileName = "mscoree.dll"; private const String strRecordRootName = "Record"; private const String strClsIdRootName = "CLSID"; private const String strTlbRootName = "TypeLib"; private static Guid s_ManagedCategoryGuid = new Guid(strManagedCategoryGuid); #endregion #region IRegistrationServices [ResourceExposure(ResourceScope.None)] [ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine)] [SecurityPermissionAttribute(SecurityAction.LinkDemand, Flags=SecurityPermissionFlag.UnmanagedCode)] public virtual bool RegisterAssembly(Assembly assembly, AssemblyRegistrationFlags flags) { // Validate the arguments. if (assembly == null) throw new ArgumentNullException("assembly"); if (assembly.ReflectionOnly) throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_AsmLoadedForReflectionOnly")); // Retrieve the assembly names. String strAsmName = assembly.FullName; if (strAsmName == null) throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_NoAsmName")); // Retrieve the assembly codebase. String strAsmCodeBase = null; if ((flags & AssemblyRegistrationFlags.SetCodeBase) != 0) { strAsmCodeBase = assembly.nGetCodeBase(false); if (strAsmCodeBase == null) throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_NoAsmCodeBase")); } // Go through all the registerable types in the assembly and register them. Type[] aTypes = GetRegistrableTypesInAssembly(assembly); int NumTypes = aTypes.Length; String strAsmVersion = assembly.GetVersion().ToString(); // Retrieve the runtime version used to build the assembly. String strRuntimeVersion = assembly.ImageRuntimeVersion; for (int cTypes = 0; cTypes < NumTypes; cTypes++) { if (IsRegisteredAsValueType(aTypes[cTypes])) RegisterValueType(aTypes[cTypes], strAsmName, strAsmVersion, strAsmCodeBase, strRuntimeVersion); else if (TypeRepresentsComType(aTypes[cTypes])) RegisterComImportedType(aTypes[cTypes], strAsmName, strAsmVersion, strAsmCodeBase, strRuntimeVersion); else RegisterManagedType(aTypes[cTypes], strAsmName, strAsmVersion, strAsmCodeBase, strRuntimeVersion); CallUserDefinedRegistrationMethod(aTypes[cTypes], true); } // If this assembly has the PIA attribute, then register it as a PIA. Object[] aPIAAttrs = assembly.GetCustomAttributes(typeof(PrimaryInteropAssemblyAttribute), false); int NumPIAAttrs = aPIAAttrs.Length; for (int cPIAAttrs = 0; cPIAAttrs < NumPIAAttrs; cPIAAttrs++) RegisterPrimaryInteropAssembly(assembly, strAsmCodeBase, (PrimaryInteropAssemblyAttribute)aPIAAttrs[cPIAAttrs]); // Return value indicating if we actually registered any types. if (aTypes.Length > 0 || NumPIAAttrs > 0) return true; else return false; } [SecurityPermissionAttribute(SecurityAction.LinkDemand, Flags=SecurityPermissionFlag.UnmanagedCode)] public virtual bool UnregisterAssembly(Assembly assembly) { bool bAllVersionsGone = true; // Validate the arguments. if (assembly == null) throw new ArgumentNullException("assembly"); if (assembly.ReflectionOnly) throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_AsmLoadedForReflectionOnly")); // Go through all the registrable types in the assembly and register them. Type[] aTypes = GetRegistrableTypesInAssembly(assembly); int NumTypes = aTypes.Length; // Retrieve the assembly version String strAsmVersion = assembly.GetVersion().ToString(); for (int cTypes = 0;cTypes < NumTypes;cTypes++) { CallUserDefinedRegistrationMethod(aTypes[cTypes], false); if (IsRegisteredAsValueType(aTypes[cTypes])) { if (!UnregisterValueType(aTypes[cTypes], strAsmVersion)) bAllVersionsGone = false; } else if (TypeRepresentsComType(aTypes[cTypes])) { if (!UnregisterComImportedType(aTypes[cTypes], strAsmVersion)) bAllVersionsGone = false; } else { if (!UnregisterManagedType(aTypes[cTypes], strAsmVersion)) bAllVersionsGone = false; } } // If this assembly has the PIA attribute, then unregister it as a PIA. Object[] aPIAAttrs = assembly.GetCustomAttributes(typeof(PrimaryInteropAssemblyAttribute),false); int NumPIAAttrs = aPIAAttrs.Length; if (bAllVersionsGone) { for (int cPIAAttrs = 0;cPIAAttrs < NumPIAAttrs;cPIAAttrs++) UnregisterPrimaryInteropAssembly(assembly, (PrimaryInteropAssemblyAttribute)aPIAAttrs[cPIAAttrs]); } // Return value indicating if we actually un-registered any types. if (aTypes.Length > 0 || NumPIAAttrs > 0) return true; else return false; } [SecurityPermissionAttribute(SecurityAction.LinkDemand, Flags=SecurityPermissionFlag.UnmanagedCode)] public virtual Type[] GetRegistrableTypesInAssembly(Assembly assembly) { // Validate the arguments. if (assembly == null) throw new ArgumentNullException("assembly"); // Retrieve the list of types in the assembly. Type[] aTypes = assembly.GetExportedTypes(); int NumTypes = aTypes.Length; // Create an array list that will be filled in. ArrayList TypeList = new ArrayList(); // Register all the types that require registration. for (int cTypes = 0; cTypes < NumTypes; cTypes++) { Type CurrentType = aTypes[cTypes]; if (TypeRequiresRegistration(CurrentType)) TypeList.Add(CurrentType); } // Copy the array list to an array and return it. Type[] RetArray = new Type[TypeList.Count]; TypeList.CopyTo(RetArray); return RetArray; } [SecurityPermissionAttribute(SecurityAction.LinkDemand, Flags=SecurityPermissionFlag.UnmanagedCode)] public virtual String GetProgIdForType(Type type) { return Marshal.GenerateProgIdForType(type); } [SecurityPermissionAttribute(SecurityAction.LinkDemand, Flags=SecurityPermissionFlag.UnmanagedCode)] public virtual void RegisterTypeForComClients(Type type, ref Guid g) { if(type == null) throw new ArgumentNullException("type"); if((type as RuntimeType) == null) throw new ArgumentException(Environment.GetResourceString("Argument_MustBeRuntimeType"),"type"); if(!TypeRequiresRegistration(type)) throw new ArgumentException(Environment.GetResourceString("Argument_TypeMustBeComCreatable"),"type"); // Call the native method to do CoRegisterClassObject RegisterTypeForComClientsNative(type, ref g); } public virtual Guid GetManagedCategoryGuid() { return s_ManagedCategoryGuid; } [SecurityPermissionAttribute(SecurityAction.LinkDemand, Flags=SecurityPermissionFlag.UnmanagedCode)] public virtual bool TypeRequiresRegistration(Type type) { return TypeRequiresRegistrationHelper(type); } public virtual bool TypeRepresentsComType(Type type) { // If the type is not a COM import, then it does not represent a COM type. if (!type.IsCOMObject) return false; // If it is marked as tdImport, then it represents a COM type directly. if (type.IsImport) return true; // If the type is derived from a tdImport class and has the same GUID as the // imported class, then it represents a COM type. Type baseComImportType = GetBaseComImportType(type); BCLDebug.Assert(baseComImportType != null, "baseComImportType != null"); if (Marshal.GenerateGuidForType(type) == Marshal.GenerateGuidForType(baseComImportType)) return true; return false; } #endregion #region Public methods not on IRegistrationServices [ComVisible(false)] [SecurityPermissionAttribute(SecurityAction.LinkDemand, Flags=SecurityPermissionFlag.UnmanagedCode)] public virtual int RegisterTypeForComClients(Type type, RegistrationClassContext classContext, RegistrationConnectionType flags) { if (type == null) throw new ArgumentNullException("type"); if ((type as RuntimeType) == null) throw new ArgumentException(Environment.GetResourceString("Argument_MustBeRuntimeType"),"type"); if (!TypeRequiresRegistration(type)) throw new ArgumentException(Environment.GetResourceString("Argument_TypeMustBeComCreatable"),"type"); // Call the native method to do CoRegisterClassObject return RegisterTypeForComClientsExNative(type, classContext, flags); } [ComVisible(false)] [SecurityPermissionAttribute(SecurityAction.LinkDemand, Flags=SecurityPermissionFlag.UnmanagedCode)] public virtual void UnregisterTypeForComClients(int cookie) { // Call the native method to do CoRevokeClassObject. CoRevokeClassObject(cookie); } #endregion #region Internal helpers [SecurityPermissionAttribute(SecurityAction.LinkDemand, Flags=SecurityPermissionFlag.UnmanagedCode)] internal static bool TypeRequiresRegistrationHelper(Type type) { // If the type is not a class or a value class, then it does not get registered. if (!type.IsClass && !type.IsValueType) return false; // If the type is abstract then it does not get registered. if (type.IsAbstract) return false; // If the does not have a public default constructor then is not creatable from COM so // it does not require registration unless it is a value class. if (!type.IsValueType && type.GetConstructor(BindingFlags.Instance | BindingFlags.Public,null,new Type[0],null) == null) return false; // All other conditions are met so check to see if the type is visible from COM. return Marshal.IsTypeVisibleFromCom(type); } #endregion #region Private helpers [ResourceExposure(ResourceScope.Machine)] [ResourceConsumption(ResourceScope.Machine)] private void RegisterValueType(Type type, String strAsmName, String strAsmVersion, String strAsmCodeBase, String strRuntimeVersion) { // Retrieve some information that will be used during the registration process. String strRecordId = "{" + Marshal.GenerateGuidForType(type).ToString().ToUpper(CultureInfo.InvariantCulture) + "}"; // Create the HKEY_CLASS_ROOT\Record key. using (RegistryKey RecordRootKey = Registry.ClassesRoot.CreateSubKey(strRecordRootName)) { // Create the HKEY_CLASS_ROOT\Record\key. using (RegistryKey RecordKey = RecordRootKey.CreateSubKey(strRecordId)) { // Create the HKEY_CLASS_ROOT\Record\ \ key. using (RegistryKey RecordVersionKey = RecordKey.CreateSubKey(strAsmVersion)) { // Set the class value. RecordVersionKey.SetValue("Class", type.FullName); // Set the assembly value. RecordVersionKey.SetValue("Assembly", strAsmName); // Set the runtime version value. RecordVersionKey.SetValue("RuntimeVersion", strRuntimeVersion); // Set the assembly code base value if a code base was specified. if (strAsmCodeBase != null) RecordVersionKey.SetValue("CodeBase", strAsmCodeBase); } } } } [ResourceExposure(ResourceScope.Machine)] [ResourceConsumption(ResourceScope.Machine)] private void RegisterManagedType(Type type, String strAsmName, String strAsmVersion, String strAsmCodeBase, String strRuntimeVersion) { // // Retrieve some information that will be used during the registration process. // String strDocString = strDocStringPrefix + type.FullName; String strClsId = "{" + Marshal.GenerateGuidForType(type).ToString().ToUpper(CultureInfo.InvariantCulture) + "}"; String strProgId = GetProgIdForType(type); // // Write the actual type information in the registry. // if (strProgId != String.Empty) { // Create the HKEY_CLASS_ROOT\ key. using (RegistryKey TypeNameKey = Registry.ClassesRoot.CreateSubKey(strProgId)) { TypeNameKey.SetValue("", strDocString); // Create the HKEY_CLASS_ROOT\ \CLSID key. using (RegistryKey ProgIdClsIdKey = TypeNameKey.CreateSubKey("CLSID")) { ProgIdClsIdKey.SetValue("", strClsId); } } } // Create the HKEY_CLASS_ROOT\CLSID key. using (RegistryKey ClsIdRootKey = Registry.ClassesRoot.CreateSubKey(strClsIdRootName)) { // Create the HKEY_CLASS_ROOT\CLSID\ key. using (RegistryKey ClsIdKey = ClsIdRootKey.CreateSubKey(strClsId)) { ClsIdKey.SetValue("", strDocString); // Create the HKEY_CLASS_ROOT\CLSID\ \InprocServer32 key. using (RegistryKey InProcServerKey = ClsIdKey.CreateSubKey("InprocServer32")) { InProcServerKey.SetValue("", strMsCorEEFileName); InProcServerKey.SetValue("ThreadingModel", strManagedTypeThreadingModel); InProcServerKey.SetValue("Class", type.FullName); InProcServerKey.SetValue("Assembly", strAsmName); InProcServerKey.SetValue("RuntimeVersion", strRuntimeVersion); if (strAsmCodeBase != null) InProcServerKey.SetValue("CodeBase", strAsmCodeBase); // Create the HKEY_CLASS_ROOT\CLSID\ \InprocServer32\ subkey using (RegistryKey VersionSubKey = InProcServerKey.CreateSubKey(strAsmVersion)) { VersionSubKey.SetValue("Class", type.FullName); VersionSubKey.SetValue("Assembly", strAsmName); VersionSubKey.SetValue("RuntimeVersion", strRuntimeVersion); if (strAsmCodeBase != null) VersionSubKey.SetValue("CodeBase", strAsmCodeBase); } if (strProgId != String.Empty) { // Create the HKEY_CLASS_ROOT\CLSID\ \ProdId key. using (RegistryKey ProgIdKey = ClsIdKey.CreateSubKey("ProgId")) { ProgIdKey.SetValue("", strProgId); } } } // Create the HKEY_CLASS_ROOT\CLSID\ \Implemented Categories\ key. using (RegistryKey CategoryKey = ClsIdKey.CreateSubKey(strImplementedCategoriesSubKey)) { using (RegistryKey ManagedCategoryKey = CategoryKey.CreateSubKey(strManagedCategoryGuid)) {} } } } // // Ensure that the managed category exists. // EnsureManagedCategoryExists(); } [ResourceExposure(ResourceScope.Machine)] [ResourceConsumption(ResourceScope.Machine)] private void RegisterComImportedType(Type type, String strAsmName, String strAsmVersion, String strAsmCodeBase, String strRuntimeVersion) { // Retrieve some information that will be used during the registration process. String strClsId = "{" + Marshal.GenerateGuidForType(type).ToString().ToUpper(CultureInfo.InvariantCulture) + "}"; // Create the HKEY_CLASS_ROOT\CLSID key. using (RegistryKey ClsIdRootKey = Registry.ClassesRoot.CreateSubKey(strClsIdRootName)) { // Create the HKEY_CLASS_ROOT\CLSID\ key. using (RegistryKey ClsIdKey = ClsIdRootKey.CreateSubKey(strClsId)) { // Create the HKEY_CLASS_ROOT\CLSID\ \InProcServer32 key. using (RegistryKey InProcServerKey = ClsIdKey.CreateSubKey("InprocServer32")) { // Set the class value. InProcServerKey.SetValue("Class", type.FullName); // Set the assembly value. InProcServerKey.SetValue("Assembly", strAsmName); // Set the runtime version value. InProcServerKey.SetValue("RuntimeVersion", strRuntimeVersion); // Set the assembly code base value if a code base was specified. if (strAsmCodeBase != null) InProcServerKey.SetValue("CodeBase", strAsmCodeBase); // Create the HKEY_CLASS_ROOT\CLSID\ \InprocServer32\ subkey using (RegistryKey VersionSubKey = InProcServerKey.CreateSubKey(strAsmVersion)) { VersionSubKey.SetValue("Class", type.FullName); VersionSubKey.SetValue("Assembly", strAsmName); VersionSubKey.SetValue("RuntimeVersion", strRuntimeVersion); if (strAsmCodeBase != null) VersionSubKey.SetValue("CodeBase", strAsmCodeBase); } } } } } [ResourceExposure(ResourceScope.None)] [ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine)] private bool UnregisterValueType(Type type, String strAsmVersion) { bool bAllVersionsGone = true; // Try to open the HKEY_CLASS_ROOT\Record key. String strRecordId = "{" + Marshal.GenerateGuidForType(type).ToString().ToUpper(CultureInfo.InvariantCulture) + "}"; using (RegistryKey RecordRootKey = Registry.ClassesRoot.OpenSubKey(strRecordRootName, true)) { if (RecordRootKey != null) { // Open the HKEY_CLASS_ROOT\Record\{RecordId} key. using (RegistryKey RecordKey = RecordRootKey.OpenSubKey(strRecordId,true)) { if (RecordKey != null) { // Delete the values we created. RecordKey.DeleteValue("Assembly",false); RecordKey.DeleteValue("Class",false); RecordKey.DeleteValue("CodeBase",false); using (RegistryKey VersionSubKey = RecordKey.OpenSubKey(strAsmVersion,true)) { if (VersionSubKey != null) { // Delete the values we created. VersionSubKey.DeleteValue("Assembly",false); VersionSubKey.DeleteValue("Class",false); VersionSubKey.DeleteValue("CodeBase",false); // delete the version sub key if no value or subkeys under it if ((VersionSubKey.SubKeyCount == 0) && (VersionSubKey.ValueCount == 0)) RecordKey.DeleteSubKey(strAsmVersion); } } // If there are sub keys left then there are versions left. if (RecordKey.SubKeyCount != 0) bAllVersionsGone = false; // If there are no other values or subkeys then we can delete the HKEY_CLASS_ROOT\Record\{RecordId}. if ((RecordKey.SubKeyCount == 0) && (RecordKey.ValueCount == 0)) RecordRootKey.DeleteSubKey(strRecordId); } } // If there are no other values or subkeys then we can delete the HKEY_CLASS_ROOT\Record. if ((RecordRootKey.SubKeyCount == 0) && (RecordRootKey.ValueCount == 0)) Registry.ClassesRoot.DeleteSubKey(strRecordRootName); } } return bAllVersionsGone; } // UnregisterManagedType // // Return : // true: All versions are gone. // false: Some versions are still left in registry [ResourceExposure(ResourceScope.None)] [ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine)] private bool UnregisterManagedType(Type type,String strAsmVersion) { bool bAllVersionsGone = true; // // Create the CLSID string. // String strClsId = "{" + Marshal.GenerateGuidForType(type).ToString().ToUpper(CultureInfo.InvariantCulture) + "}"; String strProgId = GetProgIdForType(type); // // Remove the entries under HKEY_CLASS_ROOT\CLSID key. // using (RegistryKey ClsIdRootKey = Registry.ClassesRoot.OpenSubKey(strClsIdRootName, true)) { if (ClsIdRootKey != null) { // // Remove the entries under HKEY_CLASS_ROOT\CLSID\ key. // using (RegistryKey ClsIdKey = ClsIdRootKey.OpenSubKey(strClsId, true)) { if (ClsIdKey != null) { // // Remove the entries in the HKEY_CLASS_ROOT\CLSID\ \InprocServer32 key. // using (RegistryKey InProcServerKey = ClsIdKey.OpenSubKey("InprocServer32", true)) { if (InProcServerKey != null) { // // Remove the entries in HKEY_CLASS_ROOT\CLSID\ \InprocServer32\ // using (RegistryKey VersionSubKey = InProcServerKey.OpenSubKey(strAsmVersion, true)) { if (VersionSubKey != null) { // Delete the values we created VersionSubKey.DeleteValue("Assembly",false); VersionSubKey.DeleteValue("Class",false); VersionSubKey.DeleteValue("RuntimeVersion",false); VersionSubKey.DeleteValue("CodeBase",false); // If there are no other values or subkeys then we can delete the VersionSubKey. if ((VersionSubKey.SubKeyCount == 0) && (VersionSubKey.ValueCount == 0)) InProcServerKey.DeleteSubKey(strAsmVersion); } } // If there are sub keys left then there are versions left. if (InProcServerKey.SubKeyCount != 0) bAllVersionsGone = false; // If there are no versions left, then delete the threading model and default value. if (bAllVersionsGone) { InProcServerKey.DeleteValue("",false); InProcServerKey.DeleteValue("ThreadingModel",false); } InProcServerKey.DeleteValue("Assembly",false); InProcServerKey.DeleteValue("Class",false); InProcServerKey.DeleteValue("RuntimeVersion",false); InProcServerKey.DeleteValue("CodeBase",false); // If there are no other values or subkeys then we can delete the InProcServerKey. if ((InProcServerKey.SubKeyCount == 0) && (InProcServerKey.ValueCount == 0)) ClsIdKey.DeleteSubKey("InprocServer32"); } } // remove HKEY_CLASS_ROOT\CLSID\ \ProgId // and HKEY_CLASS_ROOT\CLSID\ \Implemented Category // only when all versions are removed if (bAllVersionsGone) { // Delete the value we created. ClsIdKey.DeleteValue("",false); if (strProgId != String.Empty) { // // Remove the entries in the HKEY_CLASS_ROOT\CLSID\ \ProgId key. // using (RegistryKey ProgIdKey = ClsIdKey.OpenSubKey("ProgId", true)) { if (ProgIdKey != null) { // Delete the value we created. ProgIdKey.DeleteValue("",false); // If there are no other values or subkeys then we can delete the ProgIdSubKey. if ((ProgIdKey.SubKeyCount == 0) && (ProgIdKey.ValueCount == 0)) ClsIdKey.DeleteSubKey("ProgId"); } } } // // Remove entries in the HKEY_CLASS_ROOT\CLSID\ \Implemented Categories\ key. // using (RegistryKey CategoryKey = ClsIdKey.OpenSubKey(strImplementedCategoriesSubKey, true)) { if (CategoryKey != null) { using (RegistryKey ManagedCategoryKey = CategoryKey.OpenSubKey(strManagedCategoryGuid, true)) { if (ManagedCategoryKey != null) { // If there are no other values or subkeys then we can delete the ManagedCategoryKey. if ((ManagedCategoryKey.SubKeyCount == 0) && (ManagedCategoryKey.ValueCount == 0)) CategoryKey.DeleteSubKey(strManagedCategoryGuid); } } // If there are no other values or subkeys then we can delete the CategoryKey. if ((CategoryKey.SubKeyCount == 0) && (CategoryKey.ValueCount == 0)) ClsIdKey.DeleteSubKey(strImplementedCategoriesSubKey); } } } // If there are no other values or subkeys then we can delete the ClsIdKey. if ((ClsIdKey.SubKeyCount == 0) && (ClsIdKey.ValueCount == 0)) ClsIdRootKey.DeleteSubKey(strClsId); } } // If there are no other values or subkeys then we can delete the CLSID key. if ((ClsIdRootKey.SubKeyCount == 0) && (ClsIdRootKey.ValueCount == 0)) Registry.ClassesRoot.DeleteSubKey(strClsIdRootName); } // // Remove the entries under HKEY_CLASS_ROOT\ key. // if (bAllVersionsGone) { if (strProgId != String.Empty) { using (RegistryKey TypeNameKey = Registry.ClassesRoot.OpenSubKey(strProgId, true)) { if (TypeNameKey != null) { // Delete the values we created. TypeNameKey.DeleteValue("",false); // // Remove the entries in the HKEY_CLASS_ROOT\ \CLSID key. // using (RegistryKey ProgIdClsIdKey = TypeNameKey.OpenSubKey("CLSID", true)) { if (ProgIdClsIdKey != null) { // Delete the values we created. ProgIdClsIdKey.DeleteValue("",false); // If there are no other values or subkeys then we can delete the ProgIdClsIdKey. if ((ProgIdClsIdKey.SubKeyCount == 0) && (ProgIdClsIdKey.ValueCount == 0)) TypeNameKey.DeleteSubKey("CLSID"); } } // If there are no other values or subkeys then we can delete the TypeNameKey. if ((TypeNameKey.SubKeyCount == 0) && (TypeNameKey.ValueCount == 0)) Registry.ClassesRoot.DeleteSubKey(strProgId); } } } } } return bAllVersionsGone; } // UnregisterComImportedType // Return: // true: All version information are gone. // false: There are still some version left in registry [ResourceExposure(ResourceScope.None)] [ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine)] private bool UnregisterComImportedType(Type type, String strAsmVersion) { bool bAllVersionsGone = true; String strClsId = "{" + Marshal.GenerateGuidForType(type).ToString().ToUpper(CultureInfo.InvariantCulture) + "}"; // Try to open the HKEY_CLASS_ROOT\CLSID key. using (RegistryKey ClsIdRootKey = Registry.ClassesRoot.OpenSubKey(strClsIdRootName, true)) { if (ClsIdRootKey != null) { // Try to open the HKEY_CLASS_ROOT\CLSID\ key. using (RegistryKey ClsIdKey = ClsIdRootKey.OpenSubKey(strClsId, true)) { if (ClsIdKey != null) { // Try to open the HKEY_CLASS_ROOT\CLSID\ \InProcServer32 key. using (RegistryKey InProcServerKey = ClsIdKey.OpenSubKey("InprocServer32", true)) { if (InProcServerKey != null) { // Delete the values we created. InProcServerKey.DeleteValue("Assembly",false); InProcServerKey.DeleteValue("Class",false); InProcServerKey.DeleteValue("RuntimeVersion",false); InProcServerKey.DeleteValue("CodeBase",false); // Try to open the entries in HKEY_CLASS_ROOT\CLSID\ \InProcServer32\ using (RegistryKey VersionSubKey = InProcServerKey.OpenSubKey(strAsmVersion,true)) { if (VersionSubKey != null) { // Delete the value we created VersionSubKey.DeleteValue("Assembly",false); VersionSubKey.DeleteValue("Class",false); VersionSubKey.DeleteValue("RuntimeVersion",false); VersionSubKey.DeleteValue("CodeBase",false); // If there are no other values or subkeys then we can delete the VersionSubKey if ((VersionSubKey.SubKeyCount == 0) && (VersionSubKey.ValueCount == 0)) InProcServerKey.DeleteSubKey(strAsmVersion); } } // If there are sub keys left then there are versions left. if (InProcServerKey.SubKeyCount != 0) bAllVersionsGone = false; // If there are no other values or subkeys then we can delete the InProcServerKey. if ((InProcServerKey.SubKeyCount == 0) && (InProcServerKey.ValueCount == 0)) ClsIdKey.DeleteSubKey("InprocServer32"); } } // If there are no other values or subkeys then we can delete the ClsIdKey. if ((ClsIdKey.SubKeyCount == 0) && (ClsIdKey.ValueCount == 0)) ClsIdRootKey.DeleteSubKey(strClsId); } } // If there are no other values or subkeys then we can delete the CLSID key. if ((ClsIdRootKey.SubKeyCount == 0) && (ClsIdRootKey.ValueCount == 0)) Registry.ClassesRoot.DeleteSubKey(strClsIdRootName); } } return bAllVersionsGone; } [ResourceExposure(ResourceScope.Machine)] [ResourceConsumption(ResourceScope.Machine)] private void RegisterPrimaryInteropAssembly(Assembly assembly, String strAsmCodeBase, PrimaryInteropAssemblyAttribute attr) { // Validate that the PIA has a strong name. if (assembly.nGetPublicKey().Length == 0) throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_PIAMustBeStrongNamed")); String strTlbId = "{" + Marshal.GetTypeLibGuidForAssembly(assembly).ToString().ToUpper(CultureInfo.InvariantCulture) + "}"; String strVersion = attr.MajorVersion.ToString("x", CultureInfo.InvariantCulture) + "." + attr.MinorVersion.ToString("x", CultureInfo.InvariantCulture); // Create the HKEY_CLASS_ROOT\TypeLib key. using (RegistryKey TypeLibRootKey = Registry.ClassesRoot.CreateSubKey(strTlbRootName)) { // Create the HKEY_CLASS_ROOT\TypeLib\ key. using (RegistryKey TypeLibKey = TypeLibRootKey.CreateSubKey(strTlbId)) { // Create the HKEY_CLASS_ROOT\TypeLib\ \ key. using (RegistryKey VersionSubKey = TypeLibKey.CreateSubKey(strVersion)) { // Create the HKEY_CLASS_ROOT\TypeLib\ \PrimaryInteropAssembly key. VersionSubKey.SetValue("PrimaryInteropAssemblyName", assembly.FullName); if (strAsmCodeBase != null) VersionSubKey.SetValue("PrimaryInteropAssemblyCodeBase", strAsmCodeBase); } } } } [ResourceExposure(ResourceScope.None)] [ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine)] private void UnregisterPrimaryInteropAssembly(Assembly assembly, PrimaryInteropAssemblyAttribute attr) { String strTlbId = "{" + Marshal.GetTypeLibGuidForAssembly(assembly).ToString().ToUpper(CultureInfo.InvariantCulture) + "}"; String strVersion = attr.MajorVersion.ToString("x", CultureInfo.InvariantCulture) + "." + attr.MinorVersion.ToString("x", CultureInfo.InvariantCulture); // Try to open the HKEY_CLASS_ROOT\TypeLib key. using (RegistryKey TypeLibRootKey = Registry.ClassesRoot.OpenSubKey(strTlbRootName, true)) { if (TypeLibRootKey != null) { // Try to open the HKEY_CLASS_ROOT\TypeLib\ key. using (RegistryKey TypeLibKey = TypeLibRootKey.OpenSubKey(strTlbId, true)) { if (TypeLibKey != null) { // Try to open the HKEY_CLASS_ROOT\TypeLib \ key. using (RegistryKey VersionSubKey = TypeLibKey.OpenSubKey(strVersion, true)) { if (VersionSubKey != null) { // Delete the values we created. VersionSubKey.DeleteValue("PrimaryInteropAssemblyName",false); VersionSubKey.DeleteValue("PrimaryInteropAssemblyCodeBase",false); // If there are no other values or subkeys then we can delete the VersionKey. if ((VersionSubKey.SubKeyCount == 0) && (VersionSubKey.ValueCount == 0)) TypeLibKey.DeleteSubKey(strVersion); } } // If there are no other values or subkeys then we can delete the TypeLibKey. if ((TypeLibKey.SubKeyCount == 0) && (TypeLibKey.ValueCount == 0)) TypeLibRootKey.DeleteSubKey(strTlbId); } } // If there are no other values or subkeys then we can delete the TypeLib key. if ((TypeLibRootKey.SubKeyCount == 0) && (TypeLibRootKey.ValueCount == 0)) Registry.ClassesRoot.DeleteSubKey(strTlbRootName); } } } [ResourceExposure(ResourceScope.None)] [ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine)] private void EnsureManagedCategoryExists() { // Create the HKEY_CLASS_ROOT\Component Category key. using (RegistryKey ComponentCategoryKey = Registry.ClassesRoot.CreateSubKey(strComponentCategorySubKey)) { // Create the HKEY_CLASS_ROOT\Component Category\ key. using (RegistryKey ManagedCategoryKey = ComponentCategoryKey.CreateSubKey(strManagedCategoryGuid)) { ManagedCategoryKey.SetValue("0", strManagedCategoryDescription); } } } private void CallUserDefinedRegistrationMethod(Type type, bool bRegister) { bool bFunctionCalled = false; // Retrieve the attribute type to use to determine if a function is the requested user defined // registration function. Type RegFuncAttrType = null; if(bRegister) RegFuncAttrType = typeof(ComRegisterFunctionAttribute); else RegFuncAttrType = typeof(ComUnregisterFunctionAttribute); for(Type currType = type; !bFunctionCalled && currType != null; currType = currType.BaseType) { // Retrieve all the methods. MethodInfo[] aMethods = currType.GetMethods(BindingFlags.Instance|BindingFlags.Public|BindingFlags.NonPublic|BindingFlags.Static); int NumMethods = aMethods.Length; // Go through all the methods and check for the ComRegisterMethod custom attribute. for(int cMethods = 0;cMethods < NumMethods;cMethods++) { MethodInfo CurrentMethod = aMethods[cMethods]; // Check to see if the method has the custom attribute. if(CurrentMethod.GetCustomAttributes(RegFuncAttrType, true).Length != 0) { // Check to see if the method is static before we call it. if(!CurrentMethod.IsStatic) { if(bRegister) throw new InvalidOperationException(String.Format(CultureInfo.CurrentCulture, Environment.GetResourceString("InvalidOperation_NonStaticComRegFunction"),CurrentMethod.Name,currType.Name)); else throw new InvalidOperationException(String.Format(CultureInfo.CurrentCulture, Environment.GetResourceString("InvalidOperation_NonStaticComUnRegFunction"),CurrentMethod.Name,currType.Name)); } // Finally check that the signature is string ret void. ParameterInfo[] aParams = CurrentMethod.GetParameters(); if (CurrentMethod.ReturnType != typeof(void) || aParams == null || aParams.Length != 1 || (aParams[0].ParameterType != typeof(String) && aParams[0].ParameterType != typeof(Type))) { if(bRegister) throw new InvalidOperationException(String.Format(CultureInfo.CurrentCulture, Environment.GetResourceString("InvalidOperation_InvalidComRegFunctionSig"),CurrentMethod.Name,currType.Name)); else throw new InvalidOperationException(String.Format(CultureInfo.CurrentCulture, Environment.GetResourceString("InvalidOperation_InvalidComUnRegFunctionSig"),CurrentMethod.Name,currType.Name)); } // There can only be one register and one unregister function per type. if(bFunctionCalled) { if(bRegister) throw new InvalidOperationException(String.Format(CultureInfo.CurrentCulture, Environment.GetResourceString("InvalidOperation_MultipleComRegFunctions"),currType.Name)); else throw new InvalidOperationException(String.Format(CultureInfo.CurrentCulture, Environment.GetResourceString("InvalidOperation_MultipleComUnRegFunctions"),currType.Name)); } // The function is valid so set up the arguments to call it. Object[] objs = new Object[1]; if(aParams[0].ParameterType == typeof(String)) { // We are dealing with the string overload of the function. objs[0] = "HKEY_CLASSES_ROOT\\CLSID\\{" + Marshal.GenerateGuidForType(type).ToString().ToUpper(CultureInfo.InvariantCulture) + "}"; } else { // We are dealing with the type overload of the function. objs[0] = type; } // Invoke the COM register function. CurrentMethod.Invoke(null, objs); // Mark the function as having been called. bFunctionCalled = true; } } } } private Type GetBaseComImportType(Type type) { for (; type != null && !type.IsImport; type = type.BaseType); return type; } private bool IsRegisteredAsValueType(Type type) { if (!type.IsValueType) return false; return true; } #endregion #region FCalls and DllImports [MethodImplAttribute(MethodImplOptions.InternalCall)] private static extern void RegisterTypeForComClientsNative(Type type,ref Guid g); [MethodImplAttribute(MethodImplOptions.InternalCall)] private static extern int RegisterTypeForComClientsExNative(Type t, RegistrationClassContext clsContext, RegistrationConnectionType flags); [DllImport(Win32Native.OLE32,CharSet=CharSet.Auto,PreserveSig=false)] private static extern void CoRevokeClassObject(int cookie); #endregion } }
Link Menu
This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- NumberEdit.cs
- Pkcs9Attribute.cs
- VisualTarget.cs
- KeyGestureValueSerializer.cs
- DataServiceExpressionVisitor.cs
- AnnotationResourceCollection.cs
- Size3D.cs
- HttpInputStream.cs
- ServiceManager.cs
- XmlBaseReader.cs
- Queue.cs
- DataSourceCache.cs
- TraversalRequest.cs
- Environment.cs
- InfoCardSymmetricCrypto.cs
- TextBounds.cs
- BamlLocalizabilityResolver.cs
- VoiceInfo.cs
- MailDefinitionBodyFileNameEditor.cs
- UnhandledExceptionEventArgs.cs
- LocatorManager.cs
- OpacityConverter.cs
- TrustSection.cs
- HTTP_SERVICE_CONFIG_URLACL_PARAM.cs
- FormParameter.cs
- ErrorTableItemStyle.cs
- EventWaitHandle.cs
- NeedSkipTokenVisitor.cs
- DbCommandTree.cs
- NumberSubstitution.cs
- PtsHelper.cs
- GenericIdentity.cs
- WebServiceClientProxyGenerator.cs
- ServiceActivationException.cs
- ListViewTableRow.cs
- StylusPlugin.cs
- Int32EqualityComparer.cs
- FuncCompletionCallbackWrapper.cs
- NavigationCommands.cs
- WebScriptClientGenerator.cs
- _ConnectOverlappedAsyncResult.cs
- IncrementalHitTester.cs
- RtfControlWordInfo.cs
- DependencyObjectType.cs
- TraceXPathNavigator.cs
- ForEachAction.cs
- WebControlAdapter.cs
- BuildProviderAppliesToAttribute.cs
- XmlSchemaSimpleType.cs
- QilInvoke.cs
- OleDbException.cs
- DataTemplateSelector.cs
- BackStopAuthenticationModule.cs
- XmlSerializationWriter.cs
- AuthenticationServiceManager.cs
- GenericAuthenticationEventArgs.cs
- CompilerParameters.cs
- IgnoreDeviceFilterElementCollection.cs
- MeasurementDCInfo.cs
- SqlBuilder.cs
- SoapExtensionTypeElementCollection.cs
- FontDifferentiator.cs
- BadImageFormatException.cs
- TailCallAnalyzer.cs
- graph.cs
- RelationshipSet.cs
- TableLayoutStyle.cs
- FileLevelControlBuilderAttribute.cs
- Adorner.cs
- Module.cs
- SqlMetaData.cs
- MappingSource.cs
- VariantWrapper.cs
- SchemaTableColumn.cs
- XmlSerializer.cs
- AuthorizationSection.cs
- KnownTypeDataContractResolver.cs
- Frame.cs
- WebConfigurationHostFileChange.cs
- AddressAlreadyInUseException.cs
- GradientStopCollection.cs
- SendMailErrorEventArgs.cs
- PassportAuthenticationEventArgs.cs
- PackageRelationshipCollection.cs
- XmlArrayItemAttribute.cs
- WebPartTransformerAttribute.cs
- InnerItemCollectionView.cs
- PersonalizationAdministration.cs
- SqlParameterizer.cs
- CustomWebEventKey.cs
- EntityModelBuildProvider.cs
- DockPatternIdentifiers.cs
- Behavior.cs
- GridViewCellAutomationPeer.cs
- WeakRefEnumerator.cs
- SudsWriter.cs
- ColumnHeaderCollectionEditor.cs
- Nullable.cs
- rsa.cs
- SplashScreen.cs