Share via


Access remote registry read / write with C#

Question

Thursday, October 9, 2014 4:11 PM

Hi

I've looked at an awful lot of articles on this but don't seem to have found a reliable way of viewing registry data on a remote machine. I am an admin on that machine and have tried native C# solutions such as OpenRemoteBaseKey (eg http://msdn.microsoft.com/en-us/vstudio/8zha3xws(v=vs.89).aspx), I have tried returning reg.exe query / add and various other psexec alternatives.

For writing, PSExec seemed to be the only reliable way although it is very slow. I can deal with this but I can't wait for it for reading too.

For reading, I am seeing part of a key returned, but not all when running from code, but if I run from a command window with reg.exe, everything is returned. In particular I am trying to find the value of HKLM\Software\Microsoft\Windows NT\CurrentVersion\WinLogon\DefaultUserName.

If I run reg query "\TESTMACHINE\hklm\Software\Microsoft\Windows NT\CurrentVersion\WinLogon" /f DefaultUserName then this returns a value.

If I run this in code:

        private void button1_Click(object sender, EventArgs e)
        {

            char ditto = (char)34;
            ProcessStartInfo proc = new ProcessStartInfo();
            proc.UseShellExecute = true;
            proc.FileName = @"cmd.exe";
            //proc.Verb = "runas";
            proc.Arguments = @"/k reg.exe query " + ditto + @"\\TESTMACHINE\hklm\Software\Microsoft\Windows NT\CurrentVersion\WinLogon" + ditto + " /f DefaultUserName";
            proc.RedirectStandardOutput = false;
            proc.CreateNoWindow = true;

            var x = Process.Start(proc);
            x.WaitForExit();
           
        }

it runs but the actual value isn't returned. The same for DefaultPassword too. 

I have compiled this and run it in the exact window which I ran the reg.exe directly in (that returned the correct values). In the code above I have commented out "runas" but if this is included there is no difference.

Any pointers much appreciated, this is driving me mad.

All replies (7)

Saturday, October 11, 2014 11:09 AM ✅Answered

OK managed to sort this out - the problem was the 64bit redirection occurring. The solution was to use RegistryView.Registry64 (see new code below)

 private string registryview()
{
    RegistryKey rHive;
    try
    {

        rHive = RegistryKey.OpenRemoteBaseKey(RegistryHive.LocalMachine, "TESTMACHINE", RegistryView.Registry64);
    }
    catch (Exception)
    {
        return "offline";
    }

    var rKey = rHive.OpenSubKey("Software\\Microsoft\\Windows NT\\CurrentVersion\\WinLogon\\");
    var rItem = rKey.GetValue("DefaultUserName");
    return rItem.ToString();
}

private void button2_Click(object sender, EventArgs e)
{
    MessageBox.Show(registryview());
}

Friday, October 10, 2014 8:38 AM

Hi,

I will move this case to C# forum for better response.

Thank you for your understanding!

Best regards,

We are trying to better understand customer views on social support experience, so your participation in this interview project would be greatly appreciated if you have time. Thanks for helping make community forums a great place.
Click HERE to participate the survey.


Friday, October 10, 2014 9:32 AM

Hi bondy666,

You can read Registry Value and Registry Key in C# by using WMI class **StdRegProv. ** Using WMI query via C#, If you have the right permission to access remote machine and the registry table, I tested in my own environment, it works. 

Try to follow the code as below.

private static List<string> ReadRegistryusingWMI()
    {
        List<string> programs = new List<string>();
 
        ManagementScope scope = new ManagementScope("\\\\.\\root\\CIMV2");
        scope.Connect();
 
        string softwareRegLoc = @"Software\Microsoft\Windows\CurrentVersion\Uninstall";
 
        ManagementClass registry = new ManagementClass(scope, new ManagementPath("StdRegProv"), null);
        ManagementBaseObject inParams = registry.GetMethodParameters("EnumKey");
        inParams["hDefKey"] = 0x80000002;//HKEY_LOCAL_MACHINE
        inParams["sSubKeyName"] = softwareRegLoc;
 
        // Read Registry Key Names 
        ManagementBaseObject outParams = registry.InvokeMethod("EnumKey", inParams, null);
        string[] programGuids = outParams["sNames"] as string[];
 
        foreach (string subKeyName in programGuids)
        {
            inParams = registry.GetMethodParameters("GetStringValue");
            inParams["sSubKeyName"] = softwareRegLoc + @"\" + subKeyName;
            inParams["sValueName"] = "DisplayName";
            // Read Registry Value 
            outParams = registry.InvokeMethod("GetStringValue", inParams, null);
            if (outParams.Properties["sValue"].Value != null)
            {
                string softwareName = outParams.Properties["sValue"].Value.ToString();
                programs.Add(softwareName);
            }
        }
 
        return programs;
    }

In my scenario, I used the domain admin as account to ensure I have the permission and also turn off all the firewalls between two machines.

If the code not worked for you, I suggest you look into your firewall settings and also your account permission.

By the way, you need to add “System.Management.Dll” as reference and using System.Management in your code.

Have a nice day!

Kristin

We are trying to better understand customer views on social support experience, so your participation in this interview project would be greatly appreciated if you have time. Thanks for helping make community forums a great place.
Click HERE to participate the survey.


Friday, October 10, 2014 9:57 AM

Few days back I have to read through a remote registry and it worked.

The only thing I had to do was mentioned in the article for Granting access

http://windowsitpro.com/security/granting-users-read-access-registry

Mark Answered, if it solves your question and Vote if you found it helpful.
Rohit Arora


Friday, October 10, 2014 10:46 AM

Hi Kristin

And what happens if you use the example I require, ie

HKLM\Software\Microsoft\Windows NT\CurrentVersion\WinLogon

It's not so much I can't read a remote registry, it's getting the information from this key, SPECIFICALLY DefaultUser and DefaultPassword.

Thanks

Simon


Friday, October 10, 2014 11:14 AM

I did not see you authenticating your code to another machine. You need to be the admin of the machine that you going to access in order to read the registry.

chanmm

 

chanmm


Friday, October 10, 2014 11:36 AM

I mention in the second line of my question I am an admin on the remote machine. I can get the information I require from a reg query perfectly with no special credentials.

I noticed that even if I have a batch file on that machine that runs

 reg query "\TESTMACHINE\hklm\Software\Microsoft\Windows NT\CurrentVersion\WinLogon" /f DefaultUserName

If I run this batch with PSExec remotely it does the same thing, ie returns the value but not the data in the value, yet if I run that batch on the machine itself the data is returned too. I'm beginning to think there is some soft of restriction on this key/value.