Registry value returns null when key has spaces uwing WMI

1

When trying to retrieve the value of a registry key from a remote machine for a key that has spaces using WMI in C# (Reason for using WMI: Authentication and Impersonation needed), the GetStringValue returns null but when the key doesn't have spaces, it works perfectly. Using either the @ notation or standard " notation for strings didn't help. I tried enclosing the key in double-quotes. Didn't help either.

Here's the code I have written:

public static string GetRemoteRegistryValue(string MachineName, string username, string password)
{
    string regValue = string.Empty;
    ConnectionOptions opt = new ConnectionOptions();

    opt.Impersonation = ImpersonationLevel.Impersonate;
    opt.EnablePrivileges = true;
    opt.Username = username;
    opt.Password = password;
    opt.Impersonation = ImpersonationLevel.Impersonate;
    opt.EnablePrivileges = true;
    try
    {
        ManagementPath p = new ManagementPath("\\\\" + MachineName + "\\root\\cimv2");

        ManagementScope msc = new ManagementScope(p, opt);
        msc.Connect();

        string softwareRegLoc = "\"SOFTWARE\\VMware, Inc.\\VMware Drivers\"";
        //string softwareRegLoc = @"""SOFTWARE\SAP BusinessObjects\Suite XI 4.0\Config Manager""";

        ManagementClass registry = new ManagementClass(msc, new ManagementPath("StdRegProv"), null);
        ManagementBaseObject inParams = registry.GetMethodParameters("GetStringValue");
        inParams["hDefKey"] = 0x80000002;//HKEY_LOCAL_MACHINE
        inParams["sSubKeyName"] = softwareRegLoc;
        inParams["sValueName"] = "VmciHostDevInst";

        // Read Registry Key Names 
        ManagementBaseObject outParams = registry.InvokeMethod("GetStringValue", inParams, null);
        if (outParams.Properties["sValue"].Value != null)
        {
            regValue = outParams.Properties["sValue"].Value.ToString();
        }

    }
    catch (ManagementException Ex)
    {
    }
    catch (System.UnauthorizedAccessException Ex)
    {
    }
    catch (Exception Ex)
    {
    }
    return regValue;
}

What is the solution for this issue?

c#
wmi
asked on Stack Overflow Sep 1, 2020 by Ashwin Hariharan • edited Sep 1, 2020 by 41686d6564

1 Answer

4

Okay, two points here:

  1. You shouldn't use quotation marks. So, replace "\"SOFTWARE\\VMware, Inc.\\VMware Drivers\"" with "SOFTWARE\\VMware, Inc.\\VMware Drivers".

  2. The path that you're trying to access belongs to the 64-bit provider. In order to be able to access it (by default), your application needs to have its Platform Target set to x64. Otherwise, your application would be trying to access the HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\VMware, Inc.\VMware Drivers path, which probably doesn't exist.

Removing the quotation marks and targeting x64 worked just fine for me and I got the value of the exact path mentioned in the question.

If your Platform Target is set to x86 (or Any CPU with the Prefer 32-bit checkbox ticked) and you don't want to change it to x64, then you have to force WMI to access the 64-bit Registry Hive. Check the documentation for more info.

Here's a full example:

public static string GetRemoteRegistryValue(string MachineName, string username, string password)
{
    string regValue = string.Empty;
    ConnectionOptions opt = new ConnectionOptions();

    opt.Impersonation = ImpersonationLevel.Impersonate;
    opt.EnablePrivileges = true;
    opt.Username = username;
    opt.Password = password;
    opt.Impersonation = ImpersonationLevel.Impersonate;
    opt.EnablePrivileges = true;
    try
    {
        ManagementPath p = new ManagementPath("\\\\" + MachineName + "\\root\\cimv2");

        ManagementScope msc = new ManagementScope(p, opt);
        msc.Connect();

        string softwareRegLoc = "SOFTWARE\\VMware, Inc.\\VMware Drivers";

        ManagementClass registry = new ManagementClass(msc, new ManagementPath("StdRegProv"), null);
        ManagementBaseObject inParams = registry.GetMethodParameters("GetStringValue");
        inParams["hDefKey"] = 0x80000002;//HKEY_LOCAL_MACHINE
        inParams["sSubKeyName"] = softwareRegLoc;
        inParams["sValueName"] = "VmciHostDevInst";

        ManagementNamedValueCollection objCtx = new ManagementNamedValueCollection();
        objCtx.Add("__ProviderArchitecture", 64);
        objCtx.Add("__RequiredArchitecture", true);
        InvokeMethodOptions options = new InvokeMethodOptions(objCtx, TimeSpan.MaxValue);

        // Read Registry Key Names 
        ManagementBaseObject outParams = registry.InvokeMethod("GetStringValue", inParams, options);
        if (outParams.Properties["sValue"].Value != null)
        {
            regValue = outParams.Properties["sValue"].Value.ToString();
        }
    }
    catch (ManagementException Ex)
    {
        throw;
    }
    catch (System.UnauthorizedAccessException Ex)
    {
        throw;
    }
    catch (Exception Ex)
    {
        throw;
    }
    return regValue;
}

The code above returned the value of VmciHostDevInst while the app is targeting x86.

answered on Stack Overflow Sep 1, 2020 by 41686d6564

User contributions licensed under CC BY-SA 3.0