32-bit Windows service writing to the 64-bit registry. (AutoAdminLogon Keys) - c#

// Edit:
oh wow. It's odd that I've been working on this for a day now and just realized I needed to do:
key = key.OpenSubKey(#"SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon", true);
And then everything worked. I did not know that you had to do that. Thanks for everyone that responded. I was just messing around and searched for my key and noticed it was being placed in the wrong spot.
// Original question:
I haven't seen a working solution for this and I'm not sure if it's a bug.
I have a C# 32-bit Windows service running on Windows 7 64-bit. My goal is to write to the 64-bit registry and not the Wow6432Node subkey since for AutoAdminLogon a 64-bit system doesn't seem to check the 32-bit view of the keys.
So my code is as follows:
static public void LoginAsGuest(EventLog eventLogger)
{
RegistrySecurity userSecurity = new RegistrySecurity();
RegistryAccessRule userRule = new RegistryAccessRule("Everyone", RegistryRights.FullControl, AccessControlType.Allow);
userSecurity.AddAccessRule(userRule);
var key = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry64);
key.OpenSubKey(#"SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon", RegistryKeyPermissionCheck.ReadWriteSubTree);
if (key == null)
{
eventLogger.WriteEntry("Error accessing the registry key");
}
else
{
try
{
key.SetValue("AutoAdminLogon", "1", RegistryValueKind.String);
key.SetValue("DefaultUserName", "guest", RegistryValueKind.String);
key.SetValue("DefaultPassword", "password", RegistryValueKind.String);
}
catch (Exception exception)
{
eventLogger.WriteEntry("Problem setting up keys: " + exception);
}
}
key.Close();
Reboot();
}
No exception or error is thrown. Nothing is written to the registry in the 32-bit or 64-bit view. I've tried using:
key.OpenSubKey(#"SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon", true);
But it has the same outcome. Now if I just write without any view then my program successfully writes to the subkey:
SOFTWARE\Wow6432Node\Microsoft\Windows NT\CurrentVersion\Winlogon
Basically all I want is to write to the subkey:
SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon
Anyone know why the above code isn't writing to the requested key? (I will point out that AutoAdminLogon and the other two keys are used by the windows default credential provider such that when windows starts it checks those keys and if AutoAdminLogon is set to 1 then it logs in automatically with the given username and password. I'm doing this to allow a computer to be logged in as guest by setting the keys then rebooting the computer).

It's odd that I've been working on this for a day now and just realized I needed to do:
key = key.OpenSubKey(#"SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon", true);
And then everything worked. I did not know that you had to do that. Thanks for everyone that responded. I was just messing around and searched for my key and noticed it was being placed in the wrong spot.

Related

Cannot change registry variable C#

I'm in the middle of creating my own kiosk using C#, and for that I'm going to kill explorer (windows shell) and I don't need it to autorestart. For that cause I need to change one variable in the registry however, when I'm trying to run it from the IDE it gives me an error:
System.UnauthorizedAccessException:Access to the registry key %KEYPATH% is denied.
If I try to run the executable as an administrator, I get no error messages but nothing changes, variable is still set to "1".
I also edited the permissions for that branch in registry for current user and even everyone, giving full access to that branch in the registry. This is the C# code I have
RegistryKey explorerAutoRestart;
string ear_keypath = #"SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon";
//GETTING ACCESS ERROR HERE
explorerAutoRestart = Registry.LocalMachine.CreateSubKey(ear_keypath);
switch (status)
{
case "0":
RegistryKey key = Registry.LocalMachine.CreateSubKey(#"Software\Microsoft\Windows NT\CurrentVersion\Winlogon");
key.SetValue("AutoRestartShell", 0x00000000, RegistryValueKind.DWord);
key.Close();
break;
case "1":
explorerAutoRestart.SetValue("AutoRestartShell", 1, RegistryValueKind.DWord);
explorerAutoRestart.Close();
break;
}
I would like to know what's causing this issue and how do I change the value of
AutoRestartShell - REG_DWORD
Changing CreateSUbKey to OpenSubKey(path, true) only changed the error to
Requested registry access is not allowed.
Perhaps Windows doesn't allow external editing for that branch?
Managed to solve this issue. Apparently my keys were redirected by WOW64 and that somehow didn't give me permission to the registry branch?
Nonetheless following code saved me:
RegistryKey localMachine = RegistryKey.OpenBaseKey(Microsoft.Win32.RegistryHive.LocalMachine, RegistryView.Registry64);
RegistryKey regKey = localMachine.OpenSubKey(#"SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon", true);
regKey.SetValue("Shell", "bat.exe", RegistryValueKind.String);
regKey.Close();
Changing the Shell registry

Strange issue with Registry.GetValue()

I have used the following code to read "UserName" and "Password" from registry:
RegistryKey key = Registry.LocalMachine.OpenSubKey(#"Software\Microsoft\MSCRM");
string username = key.GetValue("UserName").ToString();
string password = key.GetValue("Password").ToString();
key.Close();
However, it appears that sometimes GetValue() returns null that means "UserName" and "Password" keys do not exist. I have looked in windows registry but actually keys are there. The strange thing is that it happens from time to time.
Any ideas?
It could be that you sometimes run the application in 32 or 64 bits. Make sure the keys exists both under
"Software\Microsoft\MSCRM"
and
"Software\Wow6432Node\Microsoft\MSCRM"
If your application run as 32bits (x86 build) it will look in that area of the registry instead.

Finding Registry Keys in C#

I am working on a project that will allow me to delete the registry key from a Windows 7 PC. Specifically I am trying to make a program that will allow me to delete a profile from the machine via the ProfileList key. My problem is no matter what I try I can't seem to read the key correctly which I want to do before I start randomly deleting stuff. My code is
RegistryKey OurKey = Registry.LocalMachine;
OurKey = OurKey.OpenSubKey(#"SOFTWARE\Microsoft\WindowsNT\CurrentVersion\ProfileList", true);
foreach (string Keyname in OurKey.GetSubKeyNames())
{
MessageBox.Show(Keyname);
}
This code runs but doesn't return anything (No MessageBox). Any ideas why not?
EDIT:
I got the top level keys to load thanks to you all but it does only show the folder/key names (Ex: S-1-5-21-3794573037-2687555854-1483818651-11661) what I need is to read the keys under that folder to see what the ProfilePath is. Would there be a better way to go about that?
As pointed out by Lloyd, your path should use "Windows NT". In case of doubt, always use regedit to go inspect the registry manually.
Edit: To go with your edit, you can simply GetValue on the keys you find, the following code should do what you're looking for:
RegistryKey OurKey = Registry.LocalMachine;
OurKey = OurKey.OpenSubKey(#"SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProfileList", true);
foreach (string Keyname in OurKey.GetSubKeyNames())
{
RegistryKey key = OurKey.OpenSubKey(Keyname);
MessageBox.Show(key.GetValue("KEY_NAME").ToString()); // Replace KEY_NAME with what you're looking for
}
Windows NT
Please do not miss space

Writing to registry in a C# application

I'm trying to write to the registry using my C# app.
I'm using the answer given here: Writing values to the registry with C#
However for some reason the key isn't added to the registry.
I'm using the following code:
string Timestamp = DateTime.Now.ToString("dd-MM-yyyy");
string key = "HKEY_LOCAL_MACHINE\\SOFTWARE\\"+Application.ProductName+"\\"+Application.ProductVersion;
string valueName = "Trial Period";
Microsoft.Win32.Registry.SetValue(key, valueName, Timestamp, Microsoft.Win32.RegistryValueKind.String);
The Application.name and Application.version 'folders' don't exists yet.
Do I have to create them first?
Also, I'm testing it on a 64b Win version so I think if I want to check the registry for the key added I have to specifically check the 32bit registry in: C:\Windows\SysWOW64\regedit.exe don't I?
First of all if you want to edit key under LocalMachine you must run your application under admin rights (better use CurrentUser it's safer or create the key in installer). You have to open key in edit mode too (OpenSubKey method) to add new subkeys. I've checked the code and it works. Here is the code.
RegistryKey key = Registry.LocalMachine.OpenSubKey("Software",true);
key.CreateSubKey("AppName");
key = key.OpenSubKey("AppName", true);
key.CreateSubKey("AppVersion");
key = key.OpenSubKey("AppVersion", true);
key.SetValue("yourkey", "yourvalue");
You can use the following code to create and open the required registry keys.
RegistryKey SoftwareKey = Registry.LocalMachine.OpenSubKey("Software",true);
RegistryKey AppNameKey = SoftwareKey.CreateSubKey("AppName");
RegistryKey AppVersionKey = AppNameKey.CreateSubKey("AppVersion");
AppVersionKey.SetValue("yourkey", "yourvalue");
You can basically use CreateSubKey for all your application settings, as it will open the key for write access, if it already exists, and create it otherwise. There is no need to create first, and then open. OpenSubKey comes in handy when you are absolutely certain the key already exists, like in this case, with "HKEY_LOCAL_MACHINE\SOFTWARE\"
Also check if your registry calls are getting virtualised. See here for more information.
It can happen if your application is not UAC aware and occurs for compatibility reasons.
Real path
HKEY_LOCAL_MACHINE\Software\FooKey
Virtual path
HKEY_USERS\<User SID>_Classes\VirtualStore\Machine\Software\FooKey
Try to open HKLM\Software first. Then create key for your program, and then create key for version. Howewer, your key could be placed at HKLM\software\WOW6432Node. Check this.
The problem is you don't have enough privileges. Here is a way that works for my:
RegistryKey myKey = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry64);
myKey = myKey.OpenSubKey(subkey, RegistryKeyPermissionCheck.ReadWriteSubTree, RegistryRights.FullControl);
if (myKey != null)
{
myKey.SetValue("DefaultPrinterId", ldiPrinters[e.RowIndex].id, RegistryValueKind.String);
myKey.Close();
}
With RegistryKey.OpenBaseKey you open the correct registry, because when you don't have permissions the registry that you write, it does in another location.
By default, your changes will be written to HKLM\SOFTWARE\WOW6432Node\... because of registry redirection. This can be quite confusing.
In order to write to HKLM\SOFTWARE\..., you need to use RegistryKey.OpenBaseKey to open the 64-bit registry:
var path = #"SOFTWARE\...";
var baseKey = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry64);
var key = baseKey.CreateSubKey(path, RegistryKeyPermissionCheck.ReadWriteSubTree);
key.SetValue(name, value, RegistryValueKind.String);
Also, you need to have permission to write to the specified registry key.
You can get permission either by assigning permissions to specific users or service accounts or by running your app in elevated mode.

Setting registry key doesn't work. Sometimes

I'm trying to set a registry key in my C# code, but it doesn't work all the time. Sometimes it does work, sometimes it doesn't. I'm starting to get crazy...
In previous projects I had no problems writing and reading to the registry, but I do now.
Here's the code I'm using:
string newVersion = "10A";
RegistryKey key = null;
try
{
key = Registry.CurrentUser.CreateSubKey("Software\\stuff1\\stuff2 " + newVersion + "\\" + newVersion + "\\stuff3\\Settings", RegistryKeyPermissionCheck.ReadWriteSubTree);
key.SetValue("CopyConvertDone", "1", RegistryValueKind.String);
key.Flush();
rep.Message("CopyConvertDone registry key set for revision: " + newVersion);
}
catch (Exception e)
{
rep.Error(e);
}
finally
{
if (key != null)
{
key.Close();
}
else
{
rep.Error("Registry key is set to null.");
}
}
What I already tried but didn't work:
- Instead of using CreateSubKey I tried OpenSubKey with the write-parameter set to true.
- Added the .Flush() method.
- Did a Thread.Pause(2000) to give it some time before progressing my program (which needs this registry key)
I don't get any error and the subkey already exists, but the value (CopyConvertDone) doesn't.
Can anyone see a problem in this code and has a possible solution?
The code looks alright to me, however if it's working some of the time then perhaps use Process Monitor to see what calls are being made to the registry and what is succeeding/failing.
Had something similar happen to me just now, and using Process Monitor as suggested by Antony I discovered Windows 7 was redirecting my writes to a key under HKCU\Software\Classes\VirtualStore\MACHINE.
Just a pointer in case anybody else has this issue.
Looks correct. Maybe try to remove Flush. From MSDN: An application should only call Flush if it must be absolute certain that registry changes are recorded to disk. In general, Flush rarely, if ever, need be used.
Your already closing the RegistryKey in the finally statement.

Categories

Resources