0

我遵循了这个 C# 示例并且能够查询一些注册表值,但不是全部:

如果我不知道它的类型,如何从远程机器获取注册表值?(C#)

我可以可靠地获取注册表项,例如 CurrentVersion、ProductName 等。但是当我尝试获取 CSDVersion 时,它失败了。

我在 .NET 2.0 和 .NET 4.0 中都进行了编译,但结果相同。我试过查询本地机器和远程机器。两者都能够返回其他注册表值,但不能返回这个特定的值。

两者都是 x64 机器(Windows 7 Ultimate 和 Windows 2008 R2),因此无论以何种方式访问​​注册表都不应该有任何问题。

我发现的一件奇怪的事情是 EnumValues 函数只返回 17 个值,而这个特定的注册表项中有 21 个。在缺少的四个中,CSDVersion 就是其中之一。

我很好奇是否有人知道为什么这四个值不会回来,但其余的都会?缺失值:

  • CSDVersion - Reg_sz
  • DigitalProductID - Reg_binary
  • DigitalProductId4 - Reg_binary
  • 产品 ID - Reg_sz

真正奇怪的是我有另一个项目,它是用 .NET 2.0 编写的,并且有一个可以做这种事情的类库。为库运行 NUnit 测试时,此查询工作正常并返回所有 21 个值。但是当通过另一个项目运行这个库时,它不起作用。

我已经逐步完成了调用该库的项目中的代码,并且在执行此操作时,它只返回 17 个条目。所以我无法解释发生了什么。

有人对下一步去哪里有任何想法吗?下面是我正在使用的确切代码,它根本不适用于上述特定情况

using System;
using System.Management;
using System.Management.Instrumentation;

namespace GetCSDVersion
{
    public enum RegHive : uint
    {
        HKEY_CLASSES_ROOT = 0x80000000,
        HKEY_CURRENT_USER = 0x80000001,
        HKEY_LOCAL_MACHINE = 0x80000002,
        HKEY_USERS = 0x80000003,
        HKEY_CURRENT_CONFIG = 0x80000005
    }

    public enum RegType
    {
        REG_SZ = 1,
        REG_EXPAND_SZ,
        REG_BINARY,
        REG_DWORD,
        REG_MULTI_SZ = 7
    }

    class Program
    {
        static void Main(string[] args)
        {
            const string strComputer = "localhost";

            ConnectionOptions options = new ConnectionOptions();
            options.Impersonation = ImpersonationLevel.Impersonate;
            options.EnablePrivileges = true;
            //options.Username = "";
            //options.Password = "";

            ManagementScope myScope = new ManagementScope("\\\\" + strComputer + "\\root\\default", options);
            ManagementPath mypath = new ManagementPath("StdRegProv");
            ManagementClass mc = new ManagementClass(myScope, mypath, null);

            object oValue = GetValue(mc, RegHive.HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion", "CSDVersion");
            Console.WriteLine(oValue.ToString());
        }

        public static object GetValue(ManagementClass mc, RegHive hDefKey, string sSubKeyName, string sValueName)
        {
            RegType rType = GetValueType(mc, hDefKey, sSubKeyName, sValueName);

            ManagementBaseObject inParams = mc.GetMethodParameters("GetStringValue");
            inParams["hDefKey"] = hDefKey;
            inParams["sSubKeyName"] = sSubKeyName;
            inParams["sValueName"] = sValueName;

            object oValue = null;

            switch (rType)
            {
                case RegType.REG_SZ:
                    ManagementBaseObject outParams = mc.InvokeMethod("GetStringValue", inParams, null);

                    if (Convert.ToUInt32(outParams["ReturnValue"]) == 0)
                    {
                        oValue = outParams["sValue"];
                    }
                    else
                    {
                        // GetStringValue call failed
                    }
                    break;

                case RegType.REG_EXPAND_SZ:
                    outParams = mc.InvokeMethod("GetExpandedStringValue", inParams, null);

                    if (Convert.ToUInt32(outParams["ReturnValue"]) == 0)
                    {
                        oValue = outParams["sValue"];
                    }
                    else
                    {
                        // GetExpandedStringValue call failed
                    }
                    break;

                case RegType.REG_MULTI_SZ:
                    outParams = mc.InvokeMethod("GetMultiStringValue", inParams, null);

                    if (Convert.ToUInt32(outParams["ReturnValue"]) == 0)
                    {
                        oValue = outParams["sValue"];
                    }
                    else
                    {
                        // GetMultiStringValue call failed
                    }
                    break;

                case RegType.REG_DWORD:
                    outParams = mc.InvokeMethod("GetDWORDValue", inParams, null);

                    if (Convert.ToUInt32(outParams["ReturnValue"]) == 0)
                    {
                        oValue = outParams["uValue"];
                    }
                    else
                    {
                        // GetDWORDValue call failed
                    }
                    break;

                case RegType.REG_BINARY:
                    outParams = mc.InvokeMethod("GetBinaryValue", inParams, null);

                    if (Convert.ToUInt32(outParams["ReturnValue"]) == 0)
                    {
                        oValue = outParams["uValue"] as byte[];
                    }
                    else
                    {
                        // GetBinaryValue call failed
                    }
                    break;
            }

            return oValue;
        }

        public static RegType GetValueType(ManagementClass mc, RegHive hDefKey, string sSubKeyName, string sValueName)
        {
            ManagementBaseObject inParams = mc.GetMethodParameters("EnumValues");
            inParams["hDefKey"] = hDefKey;
            inParams["sSubKeyName"] = sSubKeyName;

            ManagementBaseObject outParams = mc.InvokeMethod("EnumValues", inParams, null);

            if (Convert.ToUInt32(outParams["ReturnValue"]) == 0)
            {
                string[] sNames = outParams["sNames"] as String[];
                int[] iTypes = outParams["Types"] as int[];

                for (int i = 0; i < sNames.Length; i++)
                {
                    if (sNames[i] == sValueName)
                    {
                        return (RegType)iTypes[i];
                    }
                }
                // value not found
            }
            else
            {
                // EnumValues call failed
            }
            // Things have fallen apart and EnumValues didn't get us what we wanted so assume it's a string
            return RegType.REG_SZ;
        }
    }
}
4

2 回答 2

5

哇。好的,所以花了几个小时尝试调试它,我在将它发布到 StackOverflow 后不到 20 分钟就自己解决了这个问题。

我知道在某些情况下,有一种奇怪的混合注册表,其中包含 32 位和 64 位密钥。我认为它不适用于这里,因为我使用的两台机器都是 64 位的。但我忘记的是项目本身有一个指定平台目标的设置。

右键单击项目,然后转到属性。选择构建选项卡。然后将 Platform Target 从 x86(必须是默认值)更改为 Any CPU。重新编译,注册表查询工作正常。

于 2012-08-27T05:12:27.857 回答
0

在 VS 2012 中,如果选中“首选 32 位”,则行为是相同的,即使目标是“任何 CPU”。

于 2018-10-09T02:00:58.217 回答