RegistryKeyPremissionsCheck and LocalMachine does not exist in current context - c#

I tried to write a simple C# program with UI to add my own key and value in registry. I was adding it to registry so that my program can read it later when it starts and does not reconfigure itself.
RegistryKey rk = LocalMachine.OpenSubKey("HKEY_LOCAL_MACHINE\\SOFTWARE\\AMC", RegistryKeyPremissionsCheck.ReadWriteSubTree, RegistryRights.ChangePermissions | RegistryRights.ReadKey);//Get the registry key desired with ChangePermissions Rights.
RegistrySecurity rs = new RegistrySecurity();
rs.AddAccessRule(new RegistryAccessRule("Administrator", RegistryRights.FullControl, InheritanceFlags.ContainerInherit | InheritanceFlags.ObjectInherit, PropagationFlags.InheritOnly, AccessControlType.Allow));//Create access rule giving full control to the Administrator user.
rk.SetAccessControl(rs); //Apply the new access rule to this Registry Key.
rk = LocalMachine.OpenSubKey("HKEY_LOCAL_MACHINE\\SOFTWARE\\AMC", RegistryKeyPremissionsCheck.ReadWriteSubTree, RegistryRights.FullControl); // Opens the key again with full control.
rs.SetOwner(new NTAccount("Administrator"));// Set the securitys owner to be Administrator
rk.SetAccessControl(rs);// Set the key with the changed permission so Administrator is now owner.
This is the code I picked up from some question at Stackoverflow. I was trying to resolve permission issue while adding/deleting/modifying the keys.
Am I missing anything?

in you first line you are using RegistryKeyPremissionsCheck which is a variable you haven't defined yet. same goes to LocalMachine.
write the line
RegistryKey LocalMachine = Registry.LocalMachine;
before your code for LocalMachine
as for RegistryKeyPremissionsCheck.ReadWriteSubTree replace it with true if you want to edit the values under the sub key you are opening, otherwise you can put false there
if you just want to add key to the registry i would just use -
int MyNumber = 0; // Your value, doesnt have to be a number
Registry.SetValue("HKEY_LOCAL_MACHINE\\SOFTWARE\\AMC", "My User Name", MyNumber);
and to get the value
object val = Registry.GetValue("HKEY_LOCAL_MACHINE\\SOFTWARE\\AMC", "My User Name", -1);
now i put this code and it works if you have the correct permissions (you are the administrator)
RegistryKey LocalMachine = Registry.LocalMachine;
RegistryKey rk = LocalMachine.OpenSubKey("HKEY_LOCAL_MACHINE\\SOFTWARE\\AMC",
RegistryKeyPermissionCheck.ReadWriteSubTree, RegistryRights.ChangePermissions | RegistryRights.ReadKey);//Get the registry key desired with ChangePermissions Rights.
RegistrySecurity rs = new RegistrySecurity();
rs.AddAccessRule(new RegistryAccessRule("Administrator", RegistryRights.FullControl, InheritanceFlags.ContainerInherit | InheritanceFlags.ObjectInherit, PropagationFlags.InheritOnly, AccessControlType.Allow));//Create access rule giving full control to the Administrator user.
rk.SetAccessControl(rs); //Apply the new access rule to this Registry Key.
rk = LocalMachine.OpenSubKey("HKEY_LOCAL_MACHINE\\SOFTWARE\\AMC",
RegistryKeyPermissionCheck.ReadWriteSubTree, RegistryRights.FullControl); // Opens the key again with full control.
rs.SetOwner(new NTAccount("Administrator"));// Set the securities owner to be Administrator
rk.SetAccessControl(rs);
int MyNumber = 0; // Your value, doesn't have to be a number
rk.SetValue("username", MyNumber);// The username should by the dynamic part

Related

C# where to write safely in registry for all users

I 've a Windows Service which writes somes of this parameters in registry.
I want these parameters to be common to any users, means, whatever the Windows Service "RunAs".
Where you'd you recommand to write them?
I tried to write them in SOFTWARE\MyWindowsService\Server but I've permissions issues as you can see in this code.
For example here, I try to read and write in SOFTWARE\MyWindowsService\Server\Key1 and type of Key1 is string (REG_SZ)...
//Get current user for windows Service
_windowsIdentity = WindowsIdentity.GetCurrent().Name;
MessageBox.Show("Try to change registry permissions for" + _windowsIdentity); //==> LocalSystem is my current account
//Get Main windows service registry
_WindowsServiceRegKeys = Registry.LocalMachine.CreateSubKey("SOFTWARE\\THIS_WINDOWS_SERVICE_FOLDER\\SERVER", RegistryKeyPermissionCheck.ReadWriteSubTree);
RegistrySecurity rs = new RegistrySecurity();
rs = _WindowsServiceRegKeys.GetAccessControl();
//Add new permissions
rs.AddAccessRule(new RegistryAccessRule(_windowsIdentity
, RegistryRights.FullControl
, InheritanceFlags.ContainerInherit | InheritanceFlags.ObjectInherit
, PropagationFlags.InheritOnly, AccessControlType.Allow));
_WindowsServiceRegKeys.SetAccessControl(rs);
//Try to read a var
object objRetRegistryKeyValue = _WindowsServiceRegKeys.GetValue("Key1"); //ERROR: object is null
_WindowsServiceRegKeys.SetValue("Key1", "Test", RegistryValueKind.String);
Could you help me on this bug?
Thanks and regards,

How to delete registry key for specific user?

I have two users: SuperUser and MyUser. How can I delete some registry key for MyUser when I am logged in as SuperUser.
In my C# application I want to delete key by path: MyUser\Software\Microsoft\Windows\CurrentVersion\Run\MyApp.
Note I am runnnig my C# application when I am logged as SuperUser.
It seems that Microsoft.Win32.Registry class doesn't have a possibility to do that.
The profile may or may not be loaded. In order to ensure that it is loaded, you'll need to logon the user. Then you can load the profile and make changes. You'll need to pinvoke LogonUser() and LoadUserProfile().
// log on user
UserToken usertoken = null;
LogonUser(user, domain, pass, LogonType.LOGON32_LOGON_NETWORK,
LogonProvider.LOGON32_PROVIDER_DEFAULT, out usertoken));
// load the profile
PROFILEINFO p = new PROFILEINFO();
p.dwFlags = 1;
p.lpUserName = user;
p.dwSize = Marshal.SizeOf(p);
LoadUserProfile(usertoken, ref profile);
// get a handle to the registry
Microsoft.Win32.SafeHandles.SafeRegistryHandle saferh =
new Microsoft.Win32.SafeHandles.SafeRegistryHandle(profile.hProfile, false);
Microsoft.Win32.RegistryKey rk =
Microsoft.Win32.RegistryKey.FromHandle(m_RegHandle, Microsoft.Win32.RegistryView.Default);

How to assign new rights (ACL) to existing registry key without inheriting rights from parent

New rights can be set using RegistryKey.SetAccessControl(new RegistrySecurity(...)). But after that the inheritance is turned on.
Is there a way to assign new rights without turning the inheritance on?
The whole code:
void test
{
SecurityIdentifier sidAccUser = new SecurityIdentifier(WellKnownSidType.BuiltinUsersSid, null);
NTAccount ntAccUser = sidAccUser.Translate(typeof(NTAccount)) as NTAccount;
RegistryAccessRule regAcRule = new RegistryAccessRule(
ntAccUser
, RegistryRights.FullControl
, InheritanceFlags.ContainerInherit | InheritanceFlags.ObjectInherit
, PropagationFlags.None
, AccessControlType.Allow);
RegistrySecurity regSecurity = new RegistrySecurity();
regSecurity.AddAccessRule(regAcRule);
RegistryKey regKey = Registry.CurrentUser.OpenSubKey(#"ZZTEST", true);
// after that the inheritance is turned on
regKey.SetAccessControl(regSecurity);
}
I found this solution but don't want to use a COM-Server: Setting permissions and blocking inheritance from C# with SetACL
Use SetAccessRuleProtection to protect the DACL from inheritance..
regSecurity.SetAccessRuleProtection(true, false);
http://msdn.microsoft.com/en-us/library/vstudio/system.security.accesscontrol.objectsecurity.setaccessruleprotection(v=vs.100).aspx

"Cannot write to the registry key" error while editing the DisableTaskMgr value

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.

What is the difference in the registry and registry hives

When I run the following command, rKey has two values.
RegistryKey sqlServer = Registry.LocalMachine.OpenSubKey( #"SOFTWARE\Microsoft\Microsoft SQL Server", false);
When I run either of the following commands (on the same machine as the same user) I find no values;
RegistryKey sqlServer64 = RegistryKey.OpenBaseKey( RegistryHive.LocalMachine, RegistryView.Registry64);
RegistryKey sqlServer32 = RegistryKey.OpenBaseKey( RegistryHive.LocalMachine, RegistryView.Registry32 );
Can anyone point me to the answer or a description of the hives vs plain registry access?
Edit:
What I do afterwards is :
StringBuilder sbKeys = new StringBuilder();
foreach (var key in sqlServer.GetValueNames() )
{
sbKeys.AppendLine( key );
}
For all RegistryKeys. For sqlServer I see two Values, for sqlServer32 and SqlServer64 there are no values.
The problem in your second variant is that you have failed to open a sub key. Your sqlServer.GetValueNames() call operates at the root level of a particular hive.
You need it to be like this:
RegistryKey root = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry64);
RegistryKey sqlServer = root.OpenSubKey(#"SOFTWARE\Microsoft\Microsoft SQL Server");
foreach (var key in sqlServer.GetValueNames())
{ .... }
Done this way it's no different from your first variant (apart from the registry view). I expect that using the appropriate registry view will lead to the solution to your other question.
Naturally you'll want to add some error checking to the code above.

Categories

Resources