Search code examples
c#registry

Creating new key in HKCR works, but doesn't


I have the following code, which returns "Success", but searching the registry with two different tools with the search string "{3BDAAC43-E734-11D5-93AF-00105A990292}" yields no results.

 RegistryKey RK = Registry.ClassesRoot.CreateSubKey("CLSID\\{3BDAAC43-E734-11D5-93AF-00105A990292}");
 if ( RK != null ) 
     {
         MessageBox.Show("Success", "Success");
     }
 else 
     {
        MessageBox.Show("Failure", "Failure");

}

[Edit] I hate problems that I solve without knowing how, but I'm past this issue.

I'm now able to create a subkey, but I can't set any value pairs. I've found several examples how it should be done, but can't see how my code is different than them.

This is my new code. The subkey appears, but never has anything in it.

     Registry.ClassesRoot.DeleteSubKey(clsid.EntryGuid, false);

                RK.CreateSubKey(clsid.EntryGuid);
                RK.OpenSubKey(clsid.EntryGuid, true);
                RK.SetValue("(Default", clsid.RootObjectName);
                RK.CreateSubKey("InprocServer32", true);
                RK.SetValue("(Default", clsid.InprocServer32);
                RK.SetValue("(Default", clsid.ThreadingModel);
                RK.CreateSubKey("ProgID", true);
                RK.SetValue("(Default", clsid.ProgID);
                RK.CreateSubKey("TypeLib", true);
                RK.SetValue("(Default", clsid.TypeLib);
                RK.CreateSubKey("Version", true);
                RK.SetValue("(Default", clsid.Version);
                RK.Close(); 


 if ( RK != null ) 
     {
         MessageBox.Show("Success", "Success");
     }
 else 
     {
        MessageBox.Show("Failure", "Failure");

     }

In the above code, clsid is an object of class, clsRegistryCLSID, which is a part of my project:

    public clsRegistryCLSID(int ID, string hive, string rootObjectName, string ThreadingModel, string InprocServer32, string ProgID, string TypeLib, string Version, string EntryGuid)
    {

    public int ID { get; set; } 
    public string hive { get; set; }    
    public string RootObjectName { get; set; }
    public string ThreadingModel { get; set; }
    public string InprocServer32 { get; set; }  
    public string ProgID { get; set; }
    public string TypeLib { get; set; }
    public string Version { get; set; }
    public string EntryGuid { get; set; }   

Solution

  • The following shows how to add subkeys to HKEY_CLASSES_ROOT\CLSID, as well as, values and data. I searched the (Win10) registry, found subkeys with similar names, and followed the structure of existing subkeys.

    The structure of the subkey that is created in the code below is:

    enter image description here


    Create a new Windows Forms App (.NET Framework) project (name: RegistryCreateSubkeyAndValues)

    Add an Application Manifest to your project

    Note: This is used to prompt the user to execute the program as Administrator.

    • In VS menu, click Project
    • Select Add New Item...
    • Select Application Manifest File (Windows Only) (name: app.manifest)
    • Click Add

    In app.manifest, replace

    <requestedExecutionLevel level="asInvoker" uiAccess="false" />
    

    with

    <requestedExecutionLevel  level="requireAdministrator" uiAccess="false" />
    

    As can be seen in the image above, the subkeys are nested. To be in harmony with this concept, I'll create a variety of nested classes to hold the necessary information.

    I'll name the top-level class RegClsid which will be created last to avoid errors showing in Visual Studio. To keep the class names organized, I've chosen to prepend each class name with its parent's name.

    Create a class (name: RegClsidInprocServer32.cs) - name is RegClsid + InprocServer32 => RegClsidInprocServer32

    public class RegClsidInprocServer32
    {
        public string Default { get; set; }
        public string ThreadingModel { get; set; }
    }
    

    Create a class (name: RegClsidProgId.cs) - name is RegClsid + ProgId => RegClsidProgId

    public class RegClsidProgId
    {
        public string Default { get; set; }
    }
    

    Create a class (name: RegClsIdTypeLib.cs) - name is RegClsid + TypeLib => RegClsidTypeLib

    public class RegClsIdTypeLib
    {
        public string Default { get; set; }
    }
    

    Create a class (name: RegClsIdVersion.cs) - name is RegClsid + Version => RegClsidVersion

    public class RegClsIdVersion
    {
        public string Default { get; set; }
    }
    

    Create a class (name: RegClsid.cs)

    public class RegClsid
    {
        public string EntryGuid { get; set; }
        public RegClsidInprocServer32 InprocServer32 { get; set; } = new RegClsidInprocServer32();
        public RegClsidProgId ProgId { get; set; } = new RegClsidProgId();
        public RegClsIdTypeLib TypeLib { get; set; } = new RegClsIdTypeLib();
        public RegClsIdVersion Version { get; set; } = new RegClsIdVersion();
    }
    

    Add the following using directives:

    • using Microsoft.Win32;

    The following shows how to add/update a registry subkey in HKEY_CLASSES_ROOT\CLSID. using statements are used to ensure that each RegistryKey is properly disposed.

    Here's an illustration of the code below. Notice the nesting of the using statements and how the return value is used in each of the nested using statements.

    enter image description here

    AddUpdateRegClsid:

    private bool AddUpdateRegClsid(RegClsid clsid, RegistryView regView = RegistryView.Registry64)
    {
        //open HKCR hive using the specified view
        using (RegistryKey localKey = RegistryKey.OpenBaseKey(RegistryHive.ClassesRoot, regView))
        {
            if (localKey != null)
            {
                //open subkey with write permissions
                using (RegistryKey clsidKey = localKey.OpenSubKey(@"CLSID", true))
                {
                    if (clsidKey != null)
                    {
                        //create or open subkey with write permissions
                        using (RegistryKey guidKey = clsidKey.CreateSubKey(clsid.EntryGuid, true))
                        {
                            if (guidKey != null)
                            {
                                //create or open subkey 'InprocServer32' with write permissions
                                //HKCR\Clsid\<entryGuid>\InprocServer32
                                using (RegistryKey inprocServer32Key = guidKey.CreateSubKey("InprocServer32", true))
                                {
                                    if (inprocServer32Key != null)
                                    {
                                        //default
                                        inprocServer32Key.SetValue("", clsid.InprocServer32.Default, RegistryValueKind.String);
                                        
                                        //ThreadingModel
                                        inprocServer32Key.SetValue("ThreadingModel", clsid.InprocServer32.ThreadingModel, RegistryValueKind.String);
                                    }
                                }
    
                                //create or open subkey 'ProgID' with write permissions
                                //HKCR\Clsid\<entryGuid>\ProgID
                                using (RegistryKey progidKey = guidKey.CreateSubKey("ProgID", true))
                                {
                                    if (progidKey != null)
                                    {
                                        //default
                                        progidKey.SetValue("", clsid.ProgId.Default, RegistryValueKind.String);
                                    }
                                }
    
                                //create or open subkey 'TypeLib' with write permissions
                                //HKCR\Clsid\<entryGuid>\TypeLib
                                using (RegistryKey typeLibKey = guidKey.CreateSubKey("TypeLib", true))
                                {
                                    if (typeLibKey != null)
                                    {
                                        //default
                                        typeLibKey.SetValue("", clsid.TypeLib.Default, RegistryValueKind.String);
                                    }
                                }
    
                                //create or open subkey 'Version' with write permissions
                                //HKCR\Clsid\<entryGuid>\Version
                                using (RegistryKey versionKey = guidKey.CreateSubKey("Version", true))
                                {
                                    if (versionKey != null)
                                    {
                                        //default
                                        versionKey.SetValue("", clsid.Version.Default, RegistryValueKind.String);
                                    }
                                }
    
                                return true;
                            }
                        }
                    }
                }
            }
        }
    
        return false;
    }
    

    Usage 1:

    //ToDo: replace values below with desired values
    //create new instance and set values
    RegClsid clsid = new RegClsid()
    {
        EntryGuid = "{3BDAAC43-E734-11D5-93AF-00105A990292}",
        InprocServer32 = new RegClsidInprocServer32() 
        { 
            Default = "My InprocServer32 default",
            ThreadingModel = "Both"
        },
        ProgId = new RegClsidProgId()
        {
            Default = "My ProgID default"
        },
        TypeLib = new RegClsIdTypeLib()
        {
            Default = "My TypeLib default"
        },
        Version = new RegClsIdVersion()
        {
            Default = "My Version default"
        }
    };
    
    //add CLSID entry to registry
    bool result = AddUpdateRegClsid(clsid);
    
    if (result)
        MessageBox.Show($@"'HKEY_Classes_Root\CLSID\{clsid.EntryGuid}' successfully added/updated.");
    else
        MessageBox.Show($@"Error: Failed to add/update 'HKEY_Classes_Root\CLSID\{clsid.EntryGuid}'.");
    

    Usage 2:

    //ToDo: replace values below with desired values
    
    //InprocServer32 - create new instance and set value(s)
    RegClsidInprocServer32 inprocServer32 = new RegClsidInprocServer32()
    {
        Default = "My InprocServer32 default",
        ThreadingModel = "Both"
    };
    
    //ProgID - create new instance and set values
    RegClsidProgId progId = new RegClsidProgId()
    {
        Default = "My ProgID default"
    };
    
    //TypeLib - create new instance and set value(s)
    RegClsIdTypeLib typeLib = new RegClsIdTypeLib()
    {
        Default = "My TypeLib default"
    };
    
    //Version - create new instance and set value(s)
    RegClsIdVersion version = new RegClsIdVersion()
    {
        Default = "My Version default"
    };
    
    //Clsid - create new instance and set values
    RegClsid clsid = new RegClsid()
    {
        EntryGuid = "{3BDAAC43-E734-11D5-93AF-00105A990292}",
        InprocServer32 = inprocServer32,
        ProgId = progId,
        TypeLib = typeLib,
        Version = version
    };
    
    
    //add CLSID entry to registry
    bool result = AddUpdateRegClsid(clsid);
    
    if (result)
        MessageBox.Show($@"'HKEY_Classes_Root\CLSID\{clsid.EntryGuid}' successfully added/updated.");
    else
        MessageBox.Show($@"Error: Failed to add/update 'HKEY_Classes_Root\CLSID\{clsid.EntryGuid}'.");
    

    Usage 3:

    //ToDo: replace values below with desired values
    
    //InprocServer32 - create new instance and set value(s)
    RegClsidInprocServer32 inprocServer32 = new RegClsidInprocServer32();
    inprocServer32.Default = "My InprocServer32 default";
    inprocServer32.ThreadingModel = "Both";
    
    //ProgID - create new instance and set value(s)
    RegClsidProgId progId = new RegClsidProgId();
    progId.Default = "My ProgID default";
    
    //TypeLib - create new instance and set value(s)
    RegClsIdTypeLib typeLib = new RegClsIdTypeLib(); 
    typeLib.Default = "My TypeLib default";
    
    //Version - create new instance and set value(s)
    RegClsIdVersion version = new RegClsIdVersion();
    version.Default = "My Version default";
    
    //Clsid - create new instance and set values
    RegClsid clsid = new RegClsid();
    clsid.EntryGuid = "{3BDAAC43-E734-11D5-93AF-00105A990292}";
    clsid.InprocServer32 = inprocServer32;
    clsid.ProgId= progId;
    clsid.TypeLib = typeLib;
    clsid.Version = version;
    
    //add CLSID entry to registry
    bool result = AddUpdateRegClsid(clsid);
    
    if (result)
        MessageBox.Show($@"'HKEY_Classes_Root\CLSID\{clsid.EntryGuid}' successfully added/updated.");
    else
        MessageBox.Show($@"Error: Failed to add/update 'HKEY_Classes_Root\CLSID\{clsid.EntryGuid}'.");
    

    Here's the result of executing the code above:

    enter image description here

    enter image description here

    enter image description here

    enter image description here

    enter image description here


    The following shows how to delete the registry subkey and child subkeys from HKEY_CLASSES_ROOT\CLSID.

    DeleteRegClsid:

    private bool DeleteRegClsid(string entryClsid, RegistryView regView = RegistryView.Registry64)
    {
        //open HKCR hive using the specified view
        using (RegistryKey localKey = RegistryKey.OpenBaseKey(RegistryHive.ClassesRoot, regView))
        {
            if (localKey != null)
            {
                //open subkey with write permissions
                using (RegistryKey clsidKey = localKey.OpenSubKey(@"CLSID", true))
                {
                    if (clsidKey != null)
                    {
                        //delete subkey and all child subkeys
                        clsidKey.DeleteSubKeyTree(entryClsid);
    
                        return true;
                    }
                }
            }
        }
    
        return false;
    }
    

    Usage:

    string entryGuid = "{3BDAAC43-E734-11D5-93AF-00105A990292}";
    bool result = DeleteRegClsid(entryGuid);
    
    if (result)
        MessageBox.Show($@"'HKEY_Classes_Root\CLSID\{entryGuid}' successfully deleted.");
    else
        MessageBox.Show($@"Error: Failed to delete 'HKEY_Classes_Root\CLSID\{entryGuid}'.");
    

    Resources: