1

I get an UnauthorizedAccessException any time I try to call CreateSubKey in my code.

const string regKeyPath = @"Software\Apps\jp2code.net\FTMaint";

private void BuildRegistry() {
  string[] split = regKeyPath.Split('\\');
  keyMaker(Registry.LocalMachine, split, 0);
}

private static void keyMaker(RegistryKey key, string[] path, int index) {
  string keyValue = path[index++];
  RegistryKey key2;
  if (!String.IsNullOrEmpty(keyValue)) {
    string subKey = null;
    string[] subKeyNames = key.GetSubKeyNames();
    foreach (var item in subKeyNames) {
      if (keyValue == item) {
        subKey = item;
      }
    }
    if (String.IsNullOrEmpty(subKey)) {
      key2 = key.CreateSubKey(keyValue);
    } else {
      key2 = key.OpenSubKey(subKey);
    }
    //key2 = key.OpenSubKey(keyValue, String.IsNullOrEmpty(subKey));
  } else {
    key2 = key;
  }
  if (index < path.Length) {
    try {
      keyMaker(key2, path, index + 1);
    } finally {
      key2.Close();
    }
  }
}

I found a post where someone was having a similar problem >> HERE << on MSDN Social, but the solution there (to use the overloaded OpenSubKey method) only returned a NULL RegistryKey for me.

This is for a Windows Mobile 5 device emulator.

Can anyone see what I'm doing wrong?

The error is thrown the first time the code reaches a key that does not exist and tries to create it.

Thanks!

screen shot

  • You need to run your application as administrator if you want to set values in LocalMachine. Either use CurrentUser or create the key as part of installation and make it possible for everyone to have any access to the key and subkeys. – Casperah Jan 12 '12 at 18:13
  • @Casperah - Please read the question in the future. Your comment makes no sense in the context of Windows Mobile 5. – Security Hound Jan 12 '12 at 18:43
  • `CurrentUser` produces the same exception as `LocalMachine`. –  Jan 12 '12 at 19:03

3 Answers3

2

All three of these work fine for me on the WinMo 6 Emulator.

Create a root key:

using (var swKey = Registry.LocalMachine.CreateSubKey("foo"))
{
    using (var subkey = swKey.CreateSubKey("OpenNETCF"))
    {
    }
}

Create a subkey via path

using (var swKey = Registry.LocalMachine.CreateSubKey("software\\foo"))
{
    using (var subkey = swKey.CreateSubKey("OpenNETCF"))
    {
    }
}

Create a subkey directly:

using (var swKey = Registry.LocalMachine.OpenSubKey("software", true))
{
    using (var subkey = swKey.CreateSubKey("OpenNETCF"))
    {
    }
}
ctacke
  • 66,480
  • 18
  • 94
  • 155
  • OK, all three of those worked for me as well. There must be a bug in my loop. Maybe I am trying to open a subkey before the previous key is closed. ??? –  Jan 12 '12 at 20:16
  • It's probably got something to do with the recursion, yes. My bet is something is opened for write twice and it's the second attempt to open that's failing. – ctacke Jan 12 '12 at 20:19
1

I found when creating a RegistryKey instance via Registry.CurrentUser.OpenSubKey that it was read-only. So I could call GetValue but when I came to try to call SetValue I got the UnauthorizedAccessException. The trick is to call Registry.CurrentUser.OpenSubKey setting the writable parameter to true, then calls to SetValue were successful.

So instead of:

key2 = key.OpenSubKey(subKey);

use:

key2 = key.OpenSubKey(subKey, writable: true);

the same probably applies to the call to CreateSubKey.

The original question was asked in the context of Windows Mobile. I've not used Windows Mobile (not sure anyone does these days), but I expect the writeable parameter will be there.

Brian Cryer
  • 2,126
  • 18
  • 18
  • I haven't worked with Windows Mobile since 2012. Is this overload of **OpenSubKey** available in the Windows Mobile OS? I can't even test that anymore. –  Mar 05 '21 at 20:07
0

To create a key in LocalMachine during installation do something like this:

[RunInstaller(true)]
public class InstallRegistry : Installer
{
    public override void Install(System.Collections.IDictionary stateSaver)
    {
        base.Install(stateSaver);

        using (RegistryKey key = Registry.LocalMachine.CreateSubKey(@"software\..."))
        {
            RegistrySecurity rs = new RegistrySecurity();
            rs.AddAccessRule(new RegistryAccessRule(new SecurityIdentifier(WellKnownSidType.BuiltinUsersSid, null), RegistryRights.FullControl, InheritanceFlags.None, PropagationFlags.NoPropagateInherit, AccessControlType.Allow));
            key.SetAccessControl(rs);
        }
    }
    public override void Rollback(System.Collections.IDictionary savedState)
    {
        base.Rollback(savedState);
    }
}

Hope this will help you.

Casperah
  • 4,504
  • 1
  • 19
  • 13
  • I need this application to run on the emulator before I am allowed to roll it out onto test on the devices. Using your suggestion about `Registry.LocalMachine`, I changed my original code to point to `Registry.CurrentUser`, but I get the same error. –  Jan 12 '12 at 19:03