Click here to Skip to main content
14,364,487 members
Rate this:
Please Sign up or sign in to vote.
Hello, I'm trying to get the architecture and the operating system of many remote pcs. In order to do that i'm querying Win32_OperatingSystem and parsing the "Caption" for the O.S. and for the architecture im reading OSArchitecture . In Windows XP this value does not exists, so i thought that reading the HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\Environment\PROCESSOR_ARCHITECTURE would have done the trick like this code:
    Try

    Dim co As New ConnectionOptions
    co.Impersonation = ImpersonationLevel.Impersonate
    co.Authentication = AuthenticationLevel.PacketPrivacy
    co.EnablePrivileges = True

    co.Username = username
    co.Password = password

    Dim scope As New ManagementScope("\\" & machine.Text & "\root\cimv2", co)

    scope.Connect()

    Dim environmentKey, asd2 As Microsoft.Win32.RegistryKey
    Dim asd As String

    environmentKey = RegistryKey.OpenRemoteBaseKey(RegistryHive.LocalMachine, machine.Text)
    asd2 = environmentKey.OpenSubKey("SYSTEM\CurrentControlSet\Control\Session Manager\Environment", True)
    asd = asd2.GetValue("PROCESSOR_ARCHITECTURE")

    Debug.Print("asd: " + asd)

    environmentKey.Close()

Catch ex As Exception

    MessageBox.Show(ex.ToString)

End Try


My problem is: if im trying this code I get an System.Security.SecurityException: "Accessing remote registry not permitted"

I am, and i know the administrator username and password. In fact if I run a simple cmdkey /add:targetname /user:username /pass:password It works.

So why do I have to run a cmdkey /add even if i have alredy specified the username and password in the ConnectionOptions ??

P.S. Sorry for my bad English
Posted
Updated 7-Jul-15 10:50am
v2
Rate this:
Please Sign up or sign in to vote.

Solution 1

The thing is you did NOT specify a username and password for the registry access.

You tried using the ManagementScope class, which only works with WMI, not the Registry classes.

Also, if your code is running on a 32-bit machine, you're going to have problems with accessing a 64-bit registry.

So, don't use the Registry to do this. Use WMI instead. There are two ways to do this in WMI. You can either use the Standard Registry Provider in WMI or you can query the Win32_OperatingSystem[^] class to get the information you're looking for.

The Win32_OperatingSystem query method is better than the registry method as you won't run into issues with accessing a 64-bit registry from a 32-bit machine.
   
Comments
Vescoz 7-Jul-15 16:15pm
   
What u mean <blockquote class="quote"><div class="op">Quote:</div>The thing is you did NOT specify a username and password for the registry access.</blockquote>

I specify username & password in

<pre lang="vb">
co.Username = username
co.Password = password
</pre>

These are variables initialize at form load, i didn't paste the code cause it is not necessary.
I.E.
username is something like
<pre lang="vb">

Dim username, password as String
username = ".\administrator" 'since i'm connecting to pc in domain
password = "my_password"
</pre>

Also querying a x86 machine with Windows XP would give me a "Not found" error,
Due to the fact that OSArchitecture into Win32_OperatingSystem class does not exists.
Dave Kreskowiak 7-Jul-15 16:42pm
   
What do I mean? You might want to go back and read what I posted. Yeah, you put that stuff in your code, in a ManagementScope instead. BUT! the ManagementScope class DOES NOT WORK with the Registry classes you're using!

Also, on XP machines, it is very rare to find a 64-bit XP machine anywhere. In that case, I'd assume 32-bit, but....

If you really need to ID a WinXP machines arch, then you can you can use the WMI stdRegistryProvider to remotely read the key with admin credentials. The ManagementScope code you already have WILL work with this method.

UPDATE:
After a bit more Googling around, I did find this workaround to use the Registry class, but I haven't tested it so I have no idea if it's going to work:
string hostName = 192.168.1.1;

using (new NetworkConnection(@"\\" + hostName + @"\admin$", new NetworkCredential(@"ad\administrator", "TopSecret")))
{
using (RegistryKey remoteHklm = RegistryKey.OpenRemoteBaseKey(RegistryHive.LocalMachine, hostName))
{
using (RegistryKey serviceKey = remoteHklm.OpenSubKey("System\\CurrentControlSet\\Services", true))
{
if (serviceKey != null)
{
foreach (string key in serviceKey.GetSubKeyNames())
{
Console.WriteLine(key);
}
}
}

}
}
Rate this:
Please Sign up or sign in to vote.

Solution 2

All right, thank to Dave Kreskowiak and Google, i got it:
Const HKEY_current_user As String = "80000002"

Dim options As New ConnectionOptions
options.Impersonation = ImpersonationLevel.Impersonate
options.EnablePrivileges = True
options.Username = ".\administrator"
options.Password = "my_password"

Dim myScope As New ManagementScope("\\" & RemotePCHostname & "\root\default", options)
Dim mypath As New ManagementPath("StdRegProv")
Dim mc As New ManagementClass(myScope, mypath, Nothing)

Dim inParams As ManagementBaseObject = mc.GetMethodParameters("GetDWORDValue")
inParams("hDefKey") =  UInt32.Parse(HKEY_current_user,System.Globalization.NumberStyles.HexNumber) 'RegistryHive.LocalMachine
inParams("sSubKeyName") = "SYSTEM\CurrentControlSet\Control\Session Manager\Environment"
inParams("sValueName") = "PROCESSOR_ARCHITECTURE"

Dim outParams As ManagementBaseObject = mc.InvokeMethod("GetStringValue", inParams, Nothing)

If (outParams("ReturnValue").ToString() = "0") Then
    MessageBox.Show(outParams("sValue").ToString())
Else
    MessageBox.Show("Error retrieving value : " + outParams("ReturnValue").ToString())
End If
   

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)




CodeProject, 503-250 Ferrand Drive Toronto Ontario, M3C 3G8 Canada +1 416-849-8900 x 100