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.
Related
The environment I'm using might sound a bit messed up, so I will try to explain it at best.
I'm doing some experimental things with Electron. Right now, I have a simple .dll written in C# with using .NET Standard 2.0 as the base. On Electron's side, I'm using electron-edge-js, which, I think, works fine because I'm able to communicate with both of them.
So basic process goes like this,
I'm building my C# code to get my .dll's (I'm also adding reference dlls as well). Putting them into the same folder with Electron project. Starting the project to see how they did.
The problem lies at .dll's code. I'm using the following simple code,
public string RegisterUser(string username, string userkey) {
try {
RegistryKey key;
if (Microsoft.Win32.Registry.CurrentUser == null) return "Current user is null";
key = Microsoft.Win32.Registry.CurrentUser.CreateSubKey(#"SOFTWARE\Test\TestFunctions");
if (key == null) return "Key is null";
key.SetValue("uid", username);
key.SetValue("upsw", userkey);
key.Close();
return "Done";
} catch (Exception e) {
return e.ToString();
}
}
However, whenever I call this method, it always returns "Current user is null" no matter what. I tried building my .exe and running it as administrator as well. I checked the privileges in Regedit as well. They all seem fine. I'm having a kinda hard time for such an easy code. A little help would be amazing, thanks!
I created windows application ,I want to start my application on windows startup
for that i written following code in installer class. but when i am checking registry using regedit i didnt get registry value. and my application not working.
public override void Commit(IDictionary savedState)
{
base.Commit(savedState);
try
{
RegistryKey add = Registry.CurrentUser.OpenSubKey("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run", true);
add.SetValue("ToposcreenServer", "\"" + Application.ExecutablePath.ToString() + "\"");
RegistryKey key = Registry.LocalMachine.CreateSubKey(#"SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\{70E25B31-99A9-474C-8990-CE28FBCEAAD1}", RegistryKeyPermissionCheck.Default);
if (key != null)
{
key.SetValue("SystemComponent", 1, RegistryValueKind.DWord);
key.Close();
}
Directory.SetCurrentDirectory(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location));
Process.Start(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) + "\\ToposcreenServer.exe");
GLobalclass.WriteLog("Installer Executed");
}
catch (Exception ex)
{
GLobalclass.WriteLog("Installer Error :" + ex.Message);
}
}
If this is an Everyone install then that code won't write to HKCU of the installing user because the code is running with the System account credentials, not the installing user's.
Anyway, you don't need code to set the Run key. Go to the registry view in the IDE and add registry folders to get to that Run key in HKCU. Then add an item with the Nama ToposcreenSaver and the value [TARGETDIR]my.exe assuming your executable is in the Application Folder in the File System view. It's possible that it won't run anyway if it requires elevation on a UAC system.
(If this code is really in an installer class, it's also not clear why you're using Application and ExecuteablePath because an installer class is a Dll being called from an msiexec.exe process, and is nothing at all to do with whatever executable you want to run. Surely it's the name of an executable you are installing?)
You don't need to set SystemComponent in the registry key. That registry key may not be there at the time your custom action runs, and what you should really do is open your MSI file with Orca and add ARPSYSTEMCOMPONENT to the Property table, give it a value of 1.
https://msdn.microsoft.com/en-us/library/windows/desktop/aa367750(v=vs.85).aspx
If the app really is a conventional screensave this might be the best way to do it:
http://www.advancedinstaller.com/user-guide/qa-install-screensaver.html
You need to check that add is not null, as per https://msdn.microsoft.com/en-us/library/xthy8s8d(v=vs.110).aspx .
Im developing a custom browser solution with .net's Webbrowser control.
To disable the IE-Compatibilty View, I set the registry entry
Software\Microsoft\Internet Explorer\Main\FeatureControl\FEATURE_BROWSER_EMULATION:
[Sreenshot regedit] http://zbirk.mirk.at/browserreg.png "Screenshot"
i tried to use the values: dword=8000,dword=8888,dword=9000, but the webbrowser control seems to ignore these reg entries.
Maybe someone had this problems too and may help me.
The WebBrowser control definately DOES respect these keys.
Remember that while taskman may show application.exe in the name column, if you are debugging the exe name is application.vshost.exe
So in my application sI just attempt to create the key every time the app runs. If it fails to create it (because it already exists) then I continue running, if it creates the key then I inform the user that they need to restart the application.
ensure that you are not running within vshost
the app name would be different ie appname.vshost.exe
Thx for your reply, now its working.
Her is my working peace of code:
public void setIEcomp()
{
String appname = Process.GetCurrentProcess().ProcessName+".exe";
RegistryKey RK8 = Registry.LocalMachine.OpenSubKey("Software\\Microsoft\\Internet Explorer\\Main\\FeatureControl\\FEATURE_BROWSER_EMULATION",RegistryKeyPermissionCheck.ReadWriteSubTree);
int value9 = 9999;
int value8 = 8888;
Version ver = webBrowser1.Version;
int value = value9;
try
{
string[] parts = ver.ToString().Split('.');
int vn = 0;
int.TryParse(parts[0], out vn);
if (vn != 0)
{
if (vn == 9)
value = value9;
else
value = value8;
}
}
catch
{
value = value9;
}
//Setting the key in LocalMachine
if (RK8 != null)
{
try
{
RK8.SetValue(appname, value, RegistryValueKind.DWord);
RK8.Close();
}
catch(Exception ex)
{
//MessageBox.Show(ex.Message);
}
}
}
I too could not see that FEATURE_BROWSER_EMULATION made any difference in my application.
I was testing the FEATURE_BROWSER_EMULATION functionality by manually editing the registry with regedit. Nothing I did made any difference. My hosted page was still failing on any new-ish JavaScript and could not load external libraries.
I found my mistake:
I was editing the 64-bit view of the registry with regedit. My app was running as a 32-bit app and looking at the 32-bit view of the registry. That's why my changes to the registry seemed to have no impact on my application. By the way, the WPF project template defaults to "Prefer 32-bit."
Manually editing with regedit within the Wow6432Node key worked:
HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Internet Explorer\MAIN\FeatureControl\FEATURE_BROWSER_EMULATION
Of course, setting the DWORD value programmatically within your application will also work, since your 32-bit application will edit within the Wow6432Node.
An older post and solution is no longer accurate.
Running procmon and watching for FEATURE_BROWSER_EMULATION shows the following registry variables actually checked. This was for WINWORD.exe but other than that - take your pick...
HKU\S-1-5-21-[my-sid-paws-off]\SOFTWARE\Microsoft\Internet Explorer\Main\FeatureControl\FEATURE_BROWSER_EMULATION\WINWORD.EXE
HKU\S-1-5-21-[my-sid-paws-off]\SOFTWARE\Microsoft\Internet Explorer\Main\FeatureControl\FEATURE_BROWSER_EMULATION*
HKLM\SOFTWARE\Microsoft\Office\ClickToRun\REGISTRY\MACHINE\Software\Microsoft\Internet Explorer\Main\FeatureControl\FEATURE_BROWSER_EMULATION(Default)
HKLM\SOFTWARE\Microsoft\Office\ClickToRun\REGISTRY\MACHINE\Software\Microsoft\Internet Explorer\Main\FeatureControl\FEATURE_BROWSER_EMULATION\WINWORD.EXE
HKLM\SOFTWARE\Microsoft\Internet Explorer\Main\FeatureControl\FEATURE_BROWSER_EMULATION\WINWORD.EXE
HKLM\SOFTWARE\Microsoft\Office\ClickToRun\REGISTRY\MACHINE\Software\Microsoft\Internet Explorer\Main\FeatureControl\FEATURE_BROWSER_EMULATION*
HKLM\SOFTWARE\Microsoft\Internet Explorer\Main\FeatureControl\FEATURE_BROWSER_EMULATION*
// 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.
I have already looked at existing topics, so please try to refrain from dropping links here.
I want to get the value of a registry key - plain and simple. Here is what I have so far.
Registry:
1) Made a key under
Current_User\Software\Custom_Subkey\Custom_Value\Custom_key\string_value
I am trying to find the string_value
string reg_subKey = "Software\\Custom_Subkey\\Custom_Value";
RegistryKey root = Registry.CurrentUser.CreateSubKey(reg_subKey);
foreach (string keyname in root.GetValueNames())
{
textBox4.AppendText(keyname.ToString() + Environment.NewLine);
// Appends the following data to textBox4 once the foreach is completed:
// Header1
// Header2
// Header3
// Header4
// Header5
// Now I want to get the VALUES of each header:
using (RegistryKey key = root.OpenSubKey(keyname))
{
**// THIS LINE GETS HIGHLIGHTED WITH THE FOLLOWING ERROR:
"Object reference not set to an instance of an object.**"
MessageBox.Show(key.ValueCount.ToString());
}
}
Hopefully this is a simple fix. I look forward to hearing your responses.
Thanks,
Evan
I believe you want root.GetSubKeyNames() in the loop not GetValueNames()
While values is working to get the values I would suggest the following loop:
foreach(string keyname in root.GetSubKeyNames())
{
// use key to get value and set textbox4
using (RegistryKey key = root.OpenSubKey(keyname))
{
MessageBox.Show(key.ValueCount.ToString());
}
}
The OpenSubKey method does not throw an exception if the specified subkey is not found. Instead, it simply returns null. It's your responsibility as a programmer to ensure that the appropriate key was found and opened by checking the return value of the method call.
Thus, my suspicion is that the registry key that you've specified is invalid. Open up Registry Editor (regedt32.exe), and verify that you can find the key in the registry exactly as written.
If you find that the registry key is indeed located exactly where you thought it was, then the problem may be related to the WOW64 subsystem, which allows 64-bit versions of Windows to run 64-bit apps. If the value was written to the registry by a 32-bit program, you won't be able to read it with the above code from a 64-bit program (or vice versa). The simplest way to check this is to change the compilation settings for your project. For example, if you're currently compiling for x86, then change to compiling for x64, or vice versa. Registry redirection may also be getting in your way; this will check for that as well.
I wanted the very same thing and your code helped me, but as you said, it didn't work properly. So, I made some modifications and I think it works fine now! Try this:
//Just make the reference until "custom_subkey", not to the next one ("custom value")
string reg_subKey = "Software\\Custom_Subkey";
RegistryKey root = Registry.CurrentUser.CreateSubKey(reg_subKey);
//Use GetSubKeyNames, instead of GetValueNames, because now you are in a higher level
foreach (string keyname in root.GetSubKeyNames())
{
using (RegistryKey key = root.OpenSubKey(keyname))
{
foreach (string valueName in key.GetValueNames())
{
MessageBox.Show(valueName);
MessageBox.Show(key.GetValue(valueName).ToString() );
}
}
}