I have to insert this to the registry:
[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows CE Services\AutoStartOnConnect]
"AutoRun"="d:\\MyFolder\\MyProgram.exe"
How would I do this in C#?
Something like this:
string name = #"SOFTWARE\Microsoft\Windows CE Services\AutoStartOnConnect";
using (RegistryKey key = Registry.LocalMachine.OpenSubKey(name, true))
{
if (key == null)
{
// Whatever you want to do if the key isn't found
}
else
{
key.SetValue("AutoRun", #"d:\MyFolder\MyProgram.exe");
}
}
If you use CreateSubKey instead of OpenSubKey, that will create it if it doesn't already exist (or open it for write otherwise) - but I suspect that in most cases, if the key doesn't exist then that indicates the rest of the system isn't in an appropriate state for your app.
You could use the Registry class:
var path = #"Software\Microsoft\Windows CE Services\AutoStartOnConnect";
using (var key = Registry.LocalMachine.OpenSubKey(path, true))
{
if (key != null)
{
key.SetValue("AutoRun", #"d:\MyFolder\MyProgram.exe");
}
}
Related
So to my final programming project I need to rename a value inside Registry through C#, this is what I wrote so far:
public bool RenameSubKey(string parentKey, string subKeyName, string newSubKeyName)
{
if (Environment.Is64BitOperatingSystem && !Environment.Is64BitProcess)
{
RegistryKey rk64 = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry64);
rk64.OpenSubKey(parentKey);
//copy all the values
foreach (string valueName in rk64.OpenSubKey(subKeyName).GetValueNames())
{
object objValue = rk64.OpenSubKey(subKeyName).GetValue(valueName);
RegistryValueKind valKind = rk64.OpenSubKey(subKeyName).GetValueKind(valueName);
rk64.CreateSubKey(newSubKeyName).SetValue(valueName, objValue, valKind);
}
rk64.DeleteSubKeyTree(subKeyName); // Deletes old value
return true;
}
using (RegistryKey rk = Registry.LocalMachine.OpenSubKey(parentKey, false))
{
rk.OpenSubKey(parentKey);
//copy all the values
foreach (string valueName in rk.OpenSubKey(subKeyName).GetValueNames())
{
object objValue = rk.OpenSubKey(subKeyName).GetValue(valueName);
RegistryValueKind valKind = rk.OpenSubKey(subKeyName).GetValueKind(valueName);
rk.CreateSubKey(newSubKeyName).SetValue(valueName, objValue, valKind);
}
rk.DeleteSubKeyTree(subKeyName); // Deletes old value
return true;
}
}
It needs to be able to rename a 32-bit Registry value as well as a 64-bit Registry value (the application is 32-bit). Rename function simply means to create new value with the new name, copy all the data from the old one to the new one and delete the old one.
Let's take an example: There's a ListView presents all the installed application on the PC and I want to change the value UninstallString to !UninstallString with the press of a button so the users won't be able to uninstall the selected application in the ListView. The app might be 64-bit (meaning the Registry values are 64-bit and it requires a little different approach) or it can be 32-bit - Hence comes the if (Environment.Is64BitOperatingSystem && !Environment.Is64BitProcess).
So in the example I place SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\7-Zip as my path and I want to rename the value UninstallString to !UninstallString, but it quits on the foreach with an error says System.NullReferenceException: 'Object reference not set to an instance of an object.' Microsoft.Win32.RegistryKey.OpenSubKey(...) returned null.
First of all, let me say, this requieres elevated privileges, the changes are because you want to enter the registry and write in them so you need to actually tell that when you are opening the sub key. Either in 64 or 32 bit. Im not sure about the If, as pointed out before by the general, but this will work at least for 32 bits path
public static bool RenameSubKey(string parentKey, string key, string newValue)
{
if (Environment.Is64BitOperatingSystem && !Environment.Is64BitProcess)
{
RegistryKey rk64 = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry64).OpenSubKey(parentKey, RegistryKeyPermissionCheck.ReadWriteSubTree);
rk64.SetValue(key, newValue);
return true;
}
using (RegistryKey rk = Registry.LocalMachine.OpenSubKey(parentKey, RegistryKeyPermissionCheck.ReadWriteSubTree))
{
rk.SetValue(key, newValue);
return true;
}
}
Thanks to #nalnpir I fixed the rename Registry value function:
public static bool RenameSubKey(string path, string keyName, string newKeyName)
{
if (Environment.Is64BitOperatingSystem && !Environment.Is64BitProcess)
{
RegistryKey rk64 = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry64).OpenSubKey(path, RegistryKeyPermissionCheck.ReadWriteSubTree);
object objValue = rk64.GetValue(keyName);
RegistryValueKind valKind = rk64.GetValueKind(keyName);
rk64.SetValue(newKeyName, objValue, valKind);
rk64.DeleteValue(keyName);
return true;
}
using (RegistryKey rk = Registry.LocalMachine.OpenSubKey(path, RegistryKeyPermissionCheck.ReadWriteSubTree))
{
object objValue = rk.GetValue(keyName);
RegistryValueKind valKind = rk.GetValueKind(keyName);
rk.SetValue(newKeyName, objValue, valKind);
rk.DeleteValue(keyName);
return true;
}
}
Now I see that I didn't access it the right way (as he enlightened me) and thus was the error.
I have a Project and i am trying to run the installer on a new pc to test my WPF application, but the registry key is not automatically created. I have tried adding it manually but i don't know why it is not working, i am sure i am not adding the key the right way. Also i am confused since it is a new PC how do i add something that will automatically create a path?
The one that i am creating is something like this in the Image:
[VS Image][1]
HKLM -- do you have Admin right? really privileged rights?
How to test that you have enough right to write to HKLM (just call OpenSubKey):
public bool CanSetRegKeyValue(string path, string valueName, RegistryKey registry = null)
{
bool result = true;
try
{
RegistryKey registryKey = null;
if (registry == null)
{
registryKey = Registry.LocalMachine;
}
using (RegistryKey key = registryKey.OpenSubKey(path, true))
{
result = key != null;
}
}
catch (NullReferenceException)
{
result = false;
}
catch (SecurityException)
{
result = false;
}
return result;
}
and usage sample, which checking write ability to Key DefaultLevel under node HKLM\SOFTWARE\Policies\Microsoft\Windows\safer\codeidentifiers:
bool result = CanSetRegKeyValue("SOFTWARE\\Policies\\Microsoft\\Windows\\safer\\codeidentifiers\\", "DefaultLevel");
I am trying to delete a registry key sub tree which happens to be SAPI 5 user profile as shown below. The "nameofprofile" is the data value of the subkey and the subkey name is a CLSID but it comes up with an exception telling me that the subkey does not exist?
RegistryKey RegKey = Registry.CurrentUser.OpenSubKey("Software\\Microsoft\\Speech\\RecoProfiles\\Tokens\\", true);
RegKey.DeleteSubKeyTree("NameOfProfile");
You can try this.
string keyName = #"Software\Microsoft\Speech\RecoProfiles\Tokens";
using (RegistryKey key = Registry.CurrentUser.OpenSubKey(keyName, true))
{
key.DeleteSubKeyTree("NameOfProfile",false);
}
If you get the error again, you can try to run application in administrator mode.
Do a search of the string[] GetSubKeyNames() first and see if the sub key exists.
Try ignoring casing in case that is an issue.
var name = #"Software\Microsoft\Speech\RecoProfiles\Tokens";
var regKey = Registry.CurrentUser.OpenSubKey(name, true);
if (regKey != null) {
using (regKey) {
var subKeyName = "CLSID";
var actual = regKey.GetSubKeyNames()
.FirstOrDefault(n => string.Equals(n, subKeyName, StringComparison.InvariantCultureIgnoreCase));
if (actual != null) {
regKey.DeleteSubKeyTree(actual);
}
}
}
In the end I worked it out myself and I did this which worked fine. I should have said in the post that I always knew the profile name but I did not know the CLSID. No doubt there is an easier way to do this(No special permissions were required which was preferable if possible):
public static void DeleteKey (String profileName)
{
// Folder for SAPI 5 user profile tokens
String keyLocation = #"Software\Microsoft\Speech\RecoProfiles\Tokens";
RegistryKey key = Registry.CurrentUser.OpenSubKey(keyLocation, true);
// Get a list of Key names and work out which one is the "test" profile
String [] subKeyNames = key.GetSubKeyNames();
// Enumerate through the sub key names to find out which one is the "Test" profile
for(int i = 0; i < subKeyNames.Length; i++)
{
RegistryKey subKey =
Registry.CurrentUser.OpenSubKey("Software\\Microsoft\\Speech\\RecoProfiles\\Tokens\\" + subKeyNames[i]);
if(((String)subKey.GetValue("")).Equals(profileName))
{
key.DeleteSubKeyTree(subKeyNames[i]);
return;
}
}
}
I am using code below to get all instance names and server names in my local machine.
private List<string> GetInstanceName()
{
var result = new List<String>();
RegistryView registryView = Environment.Is64BitOperatingSystem ? RegistryView.Registry64 : RegistryView.Registry32;
using (RegistryKey hklm = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, registryView))
{
RegistryKey instanceKey = hklm.OpenSubKey(#"SOFTWARE\Microsoft\Microsoft SQL Server\Instance Names\SQL", false);
if (instanceKey != null)
{
foreach (var instanceName in instanceKey.GetValueNames())
{
if (!string.IsNullOrEmpty(instanceName))
{
result.Add(instanceName);
}
}
}
}
return result;
}
But I need to get version also. i dont know how to get version for each instance.
With the information you get from the registry key values in "Instance Names\SQL", you need to go back into the registry again and fetch the info you're looking for.
Try this code:
// find the installed SQL Server instance names
RegistryKey key = baseKey.OpenSubKey(#"SOFTWARE\Microsoft\Microsoft SQL Server\Instance Names\SQL");
// loop over those instances
foreach (string sqlInstance in key.GetValueNames())
{
Console.WriteLine("SQL Server instance: {0}", sqlInstance);
// find the SQL Server internal name for the instance
string internalName = key.GetValue(sqlInstance).ToString();
Console.WriteLine("\tInternal instance name: {0}", internalName);
// using that internal name - find the "Setup" node in the registry
string instanceSetupNode = string.Format(#"SOFTWARE\Microsoft\Microsoft SQL Server\{0}\Setup", internalName);
RegistryKey setupKey = baseKey.OpenSubKey(instanceSetupNode, false);
if (setupKey != null)
{
// in the "Setup" node, you have several interesting items, like
// * edition and version of that instance
// * base path for the instance itself, and for the data for that instance
string edition = setupKey.GetValue("Edition").ToString();
string pathToInstance = setupKey.GetValue("SQLBinRoot").ToString();
string version = setupKey.GetValue("Version").ToString();
Console.WriteLine("\tEdition : {0}", edition);
Console.WriteLine("\tVersion : {0}", version);
Console.WriteLine("\tPath to instance: {0}", pathToInstance);
}
}
The most reliable answer would be to use
DataTable instances = Microsoft.SqlServer.Smo.SmoApplication.EnumAvailableSqlServers(local: true);
At start up of my application I am trying to see if the user has a specific version of a software installed, specifically the MySQL connector, all using c#. In the registry, the MySQL contains a version entry. So what I am trying to accomplish is this.
My app starts up. Somewhere in the start up code I need to do the following things in order. Check to see if the user has the MySQL connector installed, which is located at...
HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\MySQL AB\MySQL Connector/Net
If the user has the connector installed, I wanted to check what version they have, which is stored as Name = "Version" and Data = x.x.x (Picture below)
Now if the user has a specific version installed, then I will execute other code, which is where I can take from.
What would be the best way of going about this?
EDIT: Below is the code I currently have and I am getting an error on line 19 (It is commented). My error says "error CS1001: Identifier Expected" I wasnt able to figure out what that means. Any help?
using System;
using Microsoft.Win32;
using System.Data;
public class regTest
{
public static void Main()
{
try
{
RegistryKey key = Registry.LocalMachine.OpenSubKey("Software\\Wow6432Node\\MySQL AB\\MySQL Connector\\Net");
if (key != null)
{
Object o = key.GetValue("Version");
if (o != null)
{
Version version = new Version(o as String); //"as" because it's REG_SZ...otherwise ToString() might be safe(r)
Version broken = new Version("6.7.4");
if (version.Equals.(broken)) //This is where the error is occuring
{
DataSet dataSet = ConfigurationManager.GetSection("system.data") as ystem.Data.DataSet;
DataView vi = dataSet.Tables[0].DefaultView;
vi.Sort = "Name";
if (vi.Find("MySql") == -1)
{
dataSet.Tables[0].Rows.Add("MySql"
, "MySql.Data.MySqlClient"
, "MySql.Data.MySqlClient"
,
typeof(MySql.Data.MySqlClient.MySqlClientFactory).AssemblyQualifiedName);
}
}
}
}
}
catch (Exception ex) //just for demonstration...it's always best to handle specific exceptions
{
//react appropriately
}
}
}
You need to first add using Microsoft.Win32; to your code page.
Then you can begin to use the Registry classes:
try
{
using (RegistryKey key = Registry.LocalMachine.OpenSubKey("Software\\Wow6432Node\\MySQL AB\\MySQL Connector\\Net"))
{
if (key != null)
{
Object o = key.GetValue("Version");
if (o != null)
{
Version version = new Version(o as String); //"as" because it's REG_SZ...otherwise ToString() might be safe(r)
//do what you like with version
}
}
}
}
catch (Exception ex) //just for demonstration...it's always best to handle specific exceptions
{
//react appropriately
}
BEWARE: unless you have administrator access, you are unlikely to be able to do much in LOCAL_MACHINE. Sometimes even reading values can be a suspect operation without admin rights.
#DonBoitnott have a good code, but require admin rights. I use this (only need Read Rights)
try
{
var subKey = "Software\\Wow6432Node\\MySQL AB\\MySQL Connector\\Net";
using (var key = Registry.LocalMachine.OpenSubKey(subKey, false)) // False is important!
{
var s = key?.GetValue("Version") as string;
if (!string.IsNullOrWhiteSpace(s))
{
var version = new Version(s);
}
}
}
catch (Exception ex) //just for demonstration...it's always best to handle specific exceptions
{
//react appropriately
}
Change:
using (RegistryKey key = Registry.LocalMachine.OpenSubKey("Software\\Wow6432Node\\MySQL AB\\MySQL Connector\\Net"))
To:
using (RegistryKey key = Registry.LocalMachine.OpenSubKey("Software\Wow6432Node\MySQL AB\MySQL Connector\Net"))