I've recently been writing an application that needs access to the following registry key :
HKLM\SOFTWARE\Wow6432Node\Classes\CLSID
For some odd reason, I'm not allowed access to this key on any system I've tested on. I'm using administrative rights and everything in between to attempt to accomplish this. I've searched through the first 5 Google result pages and still turned up empty.
Things to note :
1. The keys I'm attemping to delete may or may not contain subkeys, I've thoroughly tested "DeleteSubKey" and "DeleteSubKeyTree".
2. I've tried OpenSubKey("Key",True), both false and true values still disallowed me access.
3. I'm also not allowed access to the non-64 bit location (HKLM\Software\Classes\CLSID).
4. I've tested this on XP, 7 & 8. XP didn't give me an issue.
5. The exact error I'm receiving can be found below :
Requested registry access is not allowed. at
Microsoft.Win32.RegistryKey.OpenSubKey(String name, Boolean writable)
PLEASE help me..this has been killing me for a few days now. Any help is greatly appreciated.
Microsoft.Win32.RegistryKey m_RegEntry = Microsoft.Win32.Registry.LocalMachine;
m_RegEntry = m_RegEntry.OpenSubKey(#"SYSTEM\CurrentControlSet\Control\Class\{4D36E96D-E325-11CE-BFC1-08002BE10318}");
//string
int i = 0;
string[] m_szModemEntries = m_RegEntry.GetSubKeyNames();
This return many entries connected Devices to COM port . and an entry of "Properties" that we don't need to access.
below I am attaching a simple code to work with it.
string[] m_szModem;
Microsoft.Win32.RegistryKey m_RegEntry = Microsoft.Win32.Registry.LocalMachine;
m_RegEntry = m_RegEntry.OpenSubKey(#"SYSTEM\CurrentControlSet\Control\Class\{4D36E96D-E325-11CE-BFC1-08002BE10318}");
//string
int i = 0;
string[] m_szModemEntries = m_RegEntry.GetSubKeyNames();
m_szModem = new string[m_szModemEntries.Length];
string m_szModemPort = null;
string m_szModemName = null;
foreach (string m_szModemEntry in m_szModemEntries)
{
if (!IsNumber(m_szModemEntry))
{
}
else
{
m_RegEntry.Close();
m_RegEntry = Microsoft.Win32.Registry.LocalMachine;
string m_szKeyName = #"SYSTEM\CurrentControlSet\Control\Class\{4D36E96D-E325-11CE-BFC1-08002BE10318}\" + m_szModemEntry;
m_RegEntry = m_RegEntry.OpenSubKey(m_szKeyName);
m_szModemPort = m_RegEntry.GetValue("AttachedTo").ToString();
m_szModemName = m_RegEntry.GetValue("Model").ToString();
if (m_szModemName.Contains("<device name>"))
{
CommPort = m_szModemPort;
lbldevicename.Text = "Device connected!";
lbldevicename.ForeColor = Color.Green;
cmdProgram.Enabled = true;
DeviceConnected = true;
break;
}
CommPort = "";
cmdProgram.Enabled = false;
lbldevicename.Text = "Device not connected!";
lbldevicename.ForeColor = Color.Red;
DeviceConnected = false;
}
}
//and IsNumber Function
public Boolean IsNumber(String s)
{
foreach (Char ch in s)
{
if (!Char.IsDigit(ch)) return false;
}
return true;
}
You may need to modify the access control security. Use GetAccessControl to get the ACL for the registry key, modify it, and then save it with SetAccessControl.
Here's a solution I've found which works without Admin rights: just leave out the 'true' paramter, and it will read it all. Worked for me!
First login with Local Admin account. Then run regedit.exe and click on the registry key to be edited. From the Edit menu select premissions. Check the permissions of the related user.
I guess related accounts do not have permission to modify the registry key.
in vb.net you can use this to get access of the key before doing any operation on it
x.GetAccessControl(System.Security.AccessControl.AccessControlSections.All)
where x is any reg. key
after seeing your code i tried this and it works
Dim r As Microsoft.Win32.RegistryKey = Microsoft.Win32.Registry.LocalMachine.OpenSubKey("SOFTWARE\test", Microsoft.Win32.RegistryKeyPermissionCheck.ReadWriteSubTree)
r.DeleteSubKey("subkey", True)
Add an app.manifest in Visual studio
add item then search for application manifest file
then Replace the start of it until with this
<assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1">
<assemblyIdentity version="1.0.0.0" name="MyApplication.app"/>
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v2">
<security>
<requestedPrivileges xmlns="urn:schemas-microsoft-com:asm.v3">
</requestedPrivileges>
</security>
</trustInfo>
Related
I'm trying to add the classic "Send with MyApp" in the ContextMenu.
The fact is that my program modifies the windows registry, but it seems that it can't see the update version of it. Indeed, if I start again my program leaving the keys that it modified, it works fine.
How can I solve this (without create another program that modfies the windows registry and then call mine)?
Thank you in advance for the help.
P.s.
Here are the functions that I use to modify the registry
private void AddOption_ContextMenu()
{
RegistryKey _key1 = Registry.ClassesRoot.OpenSubKey("Folder\\shell", true);
RegistryKey _key = Registry.ClassesRoot.OpenSubKey("*\\shell", true);
RegistryKey newkey = _key.CreateSubKey("MyApp");
RegistryKey newkey1 = _key1.CreateSubKey("MyApp");
RegistryKey command = newkey.CreateSubKey("command");
RegistryKey command1 = newkey1.CreateSubKey("command");
string program = Path.GetDirectoryName(Application.ResourceAssembly.Location);
for (int i = 0; i < 3; i++)
program = Path.GetDirectoryName(program);
program = #"""" + program + #"\\MyApp\\bin\\Debug\\MyApp.exe"" ""%1""";
command.SetValue("", program);
command1.SetValue("", program);
newkey.SetValue("", "Send with MyApp");
newkey.SetValue("Icon", Path.GetDirectoryName(Application.ResourceAssembly.Location) + "\\icon.ico");
newkey1.SetValue("", "Send with MyApp");
newkey1.SetValue("Icon", Path.GetDirectoryName(Application.ResourceAssembly.Location) + "\\icon.ico");
command.Close();
command1.Close();
newkey1.Close();
newkey.Close();
_key.Close();
}
public void RemoveOption_ContextMenu()
{
RegistryKey _key = Registry.ClassesRoot.OpenSubKey("*\\shell", true);
RegistryKey _key1 = Registry.ClassesRoot.OpenSubKey("Folder\\shell", true);
_key.DeleteSubKeyTree("MyApp");
_key1.DeleteSubKeyTree("MyApp");
_key1.Close();
_key.Close();
}
Have you tried to read this?
Edited the registry with C# but cannot find the change with regedit
I found this issue years ago and I think that is mandatory to use (at least) two different C# threads to see changes in registry key -->
ref:
C# : How to change windows registry and take effect immediately
Attempting to pull the automatic update settings from the registry of a remote server. For some reason, it's returning a 0 even though a manual check of the key is 1-4. What am I overlooking? Snippet below:
ManagementScope msAutoUpdateReg = new ManagementScope(#"\\" + remoteServer + #"\root\DEFAULT:StdRegProv", connection);
msAutoUpdateReg.Connect();
ManagementClass ci = new ManagementClass(msAutoUpdateReg, new ManagementPath(#"DEFAULT:StdRegProv"), new ObjectGetOptions());
ManagementBaseObject inParams = ci.GetMethodParameters("GetDWORDValue");
inParams["hDefKey"] = 0x80000002; //HKLM
inParams["sSubKeyName"] = #"Software\Microsoft\Windows\CurrentVersion\WindowsUpdate\Auto Update";
inParams["sValueName"] = "AUOptions";
ManagementBaseObject outParams = ci.InvokeMethod("GetDWORDValue", inParams, null);
UInt32 auValue = (UInt32)outParams["uValue"];
if (auValue.ToString() != "0")
{
if (auValue == 1)
{
string currentSetting = "Keep my computer up to date has been disabled in Automatic Updates.";
}
if (auValue == 2)
{
string currentSetting = "Notify of download and installation.";
}
if (auValue == 3)
{
string currentSetting = "Automatically download and notify of installation.";
}
if (auValue == 4)
{
string currentSetting = "Automatically download and scheduled installation.";
}
}
else
{
string currentSetting = "Unknown";
}
I guess a process of elimination might help here...
1) Is this happening on just one server or are you getting this on all servers? How about on your own local machine? Is it a Windows version thing? For example it seems my Windows 10 box doesn't show the SubKey name you are looking for.
2) Do you also get zero if you change the sValueName to "foo"? Is a value of 0 representing an error?
3) Can you put a watch on outParams and check to see what values have been returned?
4) Are you being blocked by UAC, firewall or other permission issues? Can you execute other WMI commands against this server without any problems? Do you need to Run As Administrator to get this to work?
5) Are you getting an other exceptions or return values? I'm guessing you've posted just a portion of the code here so is this code inside a try/catch block?
Sorry if this sounds either vague or simplistic but I think you may need to look at what does work and what doesn't to see if you can identify a pattern.
I'm writing a small app that checks to see if a computer and current user are members of the appropriate security groups in Active Directory. I stumbled across this question LINK but it looks like it was forgotten and I'm running into the same issues as the OP. The end result is I want to be able to create an array that is very similar to running the following command from a command prompt.
gpresult /r
Here is a code sample that I have tried from the above link, I'm running into the same errors as the OP specifically "out of range" exception" when attempting to set LoggingUser and LoggingComputer. Since I can't get past these errors I'm not even sure if this method is the right route.
GPRsop rsop = new GPRsop(RsopMode.Logging, "root\\RSOP\\Computer");
rsop.LoggingComputer = "MyComputer";
rsop.LoggingUser = "domain\\user";
rsop.LoggingMode = LoggingMode.Computer;
rsop.CreateQueryResults();
rsop.GenerateReportToFile(ReportType.Xml, "C:\\Temp\\test.xml");
I found a roundabout way to accomplish what I needed by reading the registry keys located in "HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Group Policy\History" for applied group policies, added them to an ArrayList then checked to see if the list contained the policy I'm interested in.
To make sure these keys are dynamically updated, I removed the machine in question from the GPO group, rebooted and the keys associated with that policy were removed.
ArrayList groupPolicies = new ArrayList();
using (RegistryKey historyKey = Registry.LocalMachine.OpenSubKey(#"SOFTWARE\Microsoft\Windows\CurrentVersion\Group Policy\History"))
{
foreach (string historySubkey in historyKey.GetSubKeyNames())
{
using (RegistryKey guidKey = historyKey.OpenSubKey(historySubkey))
{
foreach (string guidsubkey in guidKey.GetSubKeyNames())
{
using (RegistryKey keyvalue = guidKey.OpenSubKey(guidsubkey))
{
groupPolicies.Add(keyvalue.GetValue("DisplayName"));
//Console.WriteLine(keyvalue.GetValue("DisplayName"));
}
}
}
}
}
if (!groupPolicies.Contains("replacewithyourGPOname"))
{
Console.WriteLine("The machine is not a member of the policy");
}
I'm having difficulty changing the DisableTaskMgr value in the registry. Here's what I'm trying so far:
RegistryKey taskMgr = Registry.CurrentUser.OpenSubKey("Software").OpenSubKey("Microsoft").OpenSubKey("Windows").OpenSubKey("CurrentVersion").OpenSubKey("Policies");
string[] subKeys = taskMgr.GetSubKeyNames();
bool foundSystemKey = false;
foreach (string s in subKeys)
if (s == "System")
{
foundSystemKey = true;
break;
}
if (!foundSystemKey)
{
taskMgr = taskMgr.CreateSubKey("System");
// here is where I'm getting the exception even when I do OpenSubkey("Policies" , true)
}
taskMgr.OpenSubKey("System", true);
taskMgr.SetValue("DisableTaskMgr", 1); // 0 to enable, 1 to disable.
I've also tried the following, am seeing the same error get thrown while executing the last line:
RegistrySecurity myRegSecurity = taskMgr.GetAccessControl();
string User = System.Environment.UserName;
myRegSecurity.ResetAccessRule(new RegistryAccessRule(User, RegistryRights.FullControl , AccessControlType.Allow));
taskMgr.SetAccessControl(myRegSecurity); // right here ..
Do you have any explanation as to what's going wrong? Thanks in advance :)
You likely have a permissions issue.
Open regedit, find your key ('Policies')
Right click on the key and select 'Permissions'
Permissions my be inherited, but try adding "Everyone" and re-run your code. If it works, remove "Everyone" and decide on a new group name, add the new group to either the domain, or the local machine. Then add the new group to the key and then add all users who need the permissions to the new group.
I am trying to query the following registry key values:
HKLM\SOFTWARE\Microsoft\MSSQLServer\Client\SharedMemoryOn
HKLM\SOFTWARE\Microsoft\MSSQLServer\Client\SuperSocketNetLib\ProtocolOrder
But depending on which machine I'm running the program the query returns null. When I debug on my local machine and I inspect the value for ValueCount for:
HKLM\SOFTWARE\Microsoft\MSSQLServer\Client
HKLM\SOFTWARE\Microsoft\MSSQLServer\Client\SuperSocketNetLib
The count is 0 and OpenSubKey returns null.
I am a domain admin, in the local administrators group and have added the following to my app.manifest:
<requestedExecutionLevel level="requireAdministrator" uiAccess="false" />
Any idea why?
private static void ValidateSqlClientSettings()
{
Console.WriteLine("\r\n/////////////// LOCAL SQL CLIENT PROTOCOLS ////////////////");
RegistryKey keyHKLM = Registry.LocalMachine;
///TODO: nullreferenceexception - connect to remote machine and find out why
RegistryKey sqlClientKey = keyHKLM.OpenSubKey(#"SOFTWARE\Microsoft\MSSQLServer\Client");
if (sqlClientKey == null)
{
WriteLine2Console(#"WARNING: unable to read registry key '{0}\SOFTWARE\Microsoft\MSSQLServer\Client'", ConsoleColor.Yellow);
}
var cliKeyNames = from k in sqlClientKey.GetSubKeyNames()
where k == "SuperSocketNetLib"
select k;
///TODO: find out why these values are always missing (even if I can see them in regedit)
Console.Write("Shared Memory Disabled (cliconfg): ");
if (Convert.ToBoolean(sqlClientKey.GetValue("SharedMemoryOn")))
WriteLine2Console("FAILED", ConsoleColor.Red);
else if(sqlClientKey.GetValue("SharedMemoryOn") == null)
WriteLine2Console(String.Format("WARNING - unable to read '{0}\\SharedMemoryOn'", sqlClientKey.Name), ConsoleColor.Yellow);
else
WriteLine2Console("PASS", ConsoleColor.Green);
Console.Write("Client Protocol Order (cliconfg - tcp first): ");
foreach (string cliKey in cliKeyNames)
{
RegistryKey subKey = sqlClientKey.OpenSubKey(cliKey);
object order = subKey.GetValue("ProtocolOrder");
if (order != null && order.ToString().StartsWith("tcp") == false)
{
WriteLine2Console("FAILED", ConsoleColor.Red);
}
else if (order == null)
{
WriteLine2Console(String.Format("WARNING - unable to read '{0}\\ProtocolOrder'", subKey.Name), ConsoleColor.Yellow);
}
else
{
WriteLine2Console("PASS", ConsoleColor.Green);
}
subKey.Close();
}
sqlClientKey.Close();
keyHKLM.Close();
}
Another factor you should pay attention to is application bitness.
On Windows x64, your x86 build will look for the registry keys under (in regedit) "SOFTWARE\WOW6432Node\Microsoft\MSSQLServer\Client", when you specify (in code) "Software\Microsoft\MSSQLServer\Client"
That's a WOW64 redirection for registry keys.
As Visual Studio 2010 by default creates exe in x86 mode, you should pay attention to this tip.
Try changing your sqlclientkey to the following:
RegistryKey sqlClientKey = keyHKLM.OpenSubKey(#"SOFTWARE\\Microsoft\\MSSQLServer\\Client");