C# 如何读取远程注册表项?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1566547/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-06 18:56:58  来源:igfitidea点击:

How to Read Remote Registry Keys?

c#registrywmi

提问by etoisarobot

I need to be able to read the values in a specific Registry Key from a list of Remote Computers. I can do this locally with the following code

我需要能够从远程计算机列表中读取特定注册表项中的值。我可以使用以下代码在本地执行此操作

   using Microsoft.Win32;

        RegistryKey rkey = Registry.LocalMachine;
        RegistryKey rkeySoftware=rkey.OpenSubKey("Software");
        RegistryKey rkeyVendor = rkeySoftware.OpenSubKey("VendorName");
        RegistryKey rkeyVersions = rkeyVendor.OpenSubKey("Versions");

        String[] ValueNames = rkeyVersions.GetValueNames();
        foreach (string name in ValueNames)
        {
          MessageBox.Show(name + ": " + rkeyVersions.GetValue(name).ToString());
        }

but I don't know how to get the same info for a Remote Computer. Am I even using the right approach or should I be looking at WMI or something else?

但我不知道如何为远程计算机获取相同的信息。我什至使用正确的方法还是应该查看 WMI 或其他东西?

采纳答案by CraigTP

You can achieve this through WMI, although I think you can also achieve it via the same mechanism (i.e. Microsoft.Win32 namespace classes) that you're currently using.

您可以通过 WMI 实现这一点,但我认为您也可以通过您当前使用的相同机制(即 Microsoft.Win32 命名空间类)实现它。

You need to look into the:

您需要查看以下内容:

OpenRemoteBaseKey Method

OpenRemoteBaseKey 方法

The link above gives examples. It's should be as simple as something like:

上面的链接给出了例子。它应该像这样简单:

// Open HKEY_CURRENT_USER\Environment 
// on a remote computer.
environmentKey = RegistryKey.OpenRemoteBaseKey(
                   RegistryHive.CurrentUser, remoteName).OpenSubKey(
                   "Environment");

Note, though, that'll there will be security implications in opening remote registry keys, so you may need to ensure that you have the relevant security permissions to do this. For that, you'll want to look into the:

但是请注意,打开远程注册表项会带来安全隐患,因此您可能需要确保拥有相关的安全权限才能执行此操作。为此,您需要查看:

SecurityPermission

安全权限

and

RegistryPermission

注册表权限

classes in the System.Security.Permissionsnamespace.

System.Security.Permissions命名空间中的类。

回答by On Freund

The win32 API allows you to specify a computer name through RegConnectRegistry. I'm not sure that the .NET wrappers exposes this. You can also use WMI as you mentioned.

win32 API 允许您通过RegConnectRegistry指定计算机名称。我不确定 .NET 包装器是否公开了这一点。您也可以使用您提到的 WMI。

回答by Jerry Coffin

Look up OpenRemoteBaseKey().

查找 OpenRemoteBaseKey()。

回答by etoisarobot

I found that I could as CraigTP showed use the OpenRemoteBaseKey() method however it required me to change the permissions in the registry on the dest computers.

我发现我可以像 CraigTP 显示的那样使用 OpenRemoteBaseKey() 方法,但是它要求我更改目标计算机上注册表中的权限。

Here is the code I wrote that worked once I changed the permissions.

这是我编写的代码,一旦我更改了权限,它就会起作用。

RegistryKey rkey = RegistryKey.OpenRemoteBaseKey(RegistryHive.LocalMachine, "RemoteComputer");
RegistryKey rkeySoftware = rkey.OpenSubKey("Software");
RegistryKey rkeyVendor = rkeySoftware.OpenSubKey("VendorName");
RegistryKey rkeyVersions = rkeyVendor.OpenSubKey("Versions");

String[] ValueNames = rkeyVersions.GetValueNames();
foreach (string name in ValueNames)
{
    MessageBox.Show(name + ": " + rkeyVersions.GetValue(name).ToString());
}

I also found that I could get the same info using WMI without having to modify the permissions. Here is the code with WMI.

我还发现我可以使用 WMI 获得相同的信息而无需修改权限。这是带有 WMI 的代码。

ManagementScope ms = new ManagementScope();
ms.Path.Server = "flebbe";
ms.Path.NamespacePath = "root\default";
ms.Options.EnablePrivileges = true;
ms.Connect();

ManagementClass mc = new ManagementClass("stdRegProv");
mc.Scope = ms;

ManagementBaseObject mbo;
mbo = mc.GetMethodParameters("EnumValues");

mbo.SetPropertyValue("sSubKeyName", "SOFTWARE\VendorName\Versions");

string[] subkeys = (string[])mc.InvokeMethod("EnumValues", mbo, null).Properties["sNames"].Value;

ManagementBaseObject mboS;
string keyValue;

foreach (string strKey in subkeys)
{
    mboS = mc.GetMethodParameters("GetStringValue");
    mboS.SetPropertyValue("sSubKeyName", "SOFTWARE\VendorName\Versions");
    mboS.SetPropertyValue("sValueName", strKey);

    keyValue = mc.InvokeMethod("GetStringValue", mboS, null).Properties["sValue"].Value.ToString();
    MessageBox.Show(strKey + " : " + keyValue);
}

P.S. I am calling the GetStringValue() method in the loop as I know all the values are strings. If there are multiple data types you would need to read the datatype from the Types output parameter of the EnumValues method.

PS 我在循环中调用 GetStringValue() 方法,因为我知道所有值都是字符串。如果有多种数据类型,您需要从 EnumValues 方法的 Types 输出参数中读取数据类型。

回答by Rhyous

A commenter on my blog asked me to post my solution on stack overflow, so here it is.

我博客上的一位评论者要求我在堆栈溢出上发布我的解决方案,所以就在这里。

How to authenticate and access the registry remotely using C#

如何使用 C# 远程验证和访问注册表

It is basically the same as CraigTP's answer, but it includes a nice class for authenticating to the remote device.

它与 CraigTP 的答案基本相同,但它包含一个很好的类,用于对远程设备进行身份验证。

And the code is in production and tested.

并且代码正在生产中并经过测试。

回答by Robert Fey

This is the solution I went with in the end:

这是我最终采用的解决方案:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;


// add a reference to Cassia (MIT license)
// https://code.google.com/p/cassia/

using Microsoft.Win32; 

namespace RemoteRegistryRead2
{
    class Program
    {
        static void Main(string[] args)
        {
            String domain = "theDomain";
            String user = "theUserName";
            String password = "thePassword";
            String host = "machine-x11";


            using (Cassia.UserImpersonationContext userContext = new Cassia.UserImpersonationContext(domain + "\" + user, password))
            {
                string userName = System.Security.Principal.WindowsIdentity.GetCurrent().Name;
                System.Console.WriteLine("userName: " + userName);

                RegistryKey baseKey = RegistryKey.OpenRemoteBaseKey(RegistryHive.LocalMachine, host);
                RegistryKey key = baseKey.OpenSubKey(@"SYSTEM\CurrentControlSet\Control\ComputerName\ComputerName");

                String computerName = key.GetValue("ComputerName").ToString();
                Console.WriteLine(computerName);
            }
        }
    }
}

Works like a charm :]

奇迹般有效 :]

回答by Domenico Zinzi

Easy example in c# installed programs via windows registry (remote: OpenRemoteBaseKey)

通过 Windows 注册表安装的 c# 程序中的简单示例(远程:OpenRemoteBaseKey)

using Microsoft.Win32;
using System;
using System.Collections.Generic;
using System.Text;
using System.IO;


namespace SoftwareInventory
{
    class Program
    {
        static void Main(string[] args)
        {
            //!!!!! Must be launched with a domain administrator user!!!!!
            Console.ForegroundColor = ConsoleColor.Green;
            StringBuilder sbOutFile = new StringBuilder();
            Console.WriteLine("DisplayName;IdentifyingNumber");
            sbOutFile.AppendLine("Machine;DisplayName;Version");

            //Retrieve machine name from the file :File_In/collectionMachines.txt
            //string[] lines = new string[] { "NameMachine" };
            string[] lines = File.ReadAllLines(@"File_In/collectionMachines.txt");
            foreach (var machine in lines)
            {
                //Retrieve the list of installed programs for each extrapolated machine name
                var registry_key = @"SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall";
                using (Microsoft.Win32.RegistryKey key = RegistryKey.OpenRemoteBaseKey(RegistryHive.LocalMachine, machine).OpenSubKey(registry_key))
                {
                    foreach (string subkey_name in key.GetSubKeyNames())
                    {
                        using (RegistryKey subkey = key.OpenSubKey(subkey_name))
                        {
                            //Console.WriteLine(subkey.GetValue("DisplayName"));
                            //Console.WriteLine(subkey.GetValue("IdentifyingNumber"));
                            if (subkey.GetValue("DisplayName") != null)
                            {
                                Console.WriteLine(string.Format("{0};{1};{2}", machine, subkey.GetValue("DisplayName"), subkey.GetValue("Version")));
                                sbOutFile.AppendLine(string.Format("{0};{1};{2}", machine, subkey.GetValue("DisplayName"), subkey.GetValue("Version")));
                            }
                        }
                    }
                }
            }
            //CSV file creation
            var fileOutName = string.Format(@"File_Out\{0}_{1}.csv", "Software_Inventory", DateTime.Now.ToString("yyyy_MM_dd_HH_mmssfff"));
            using (var file = new System.IO.StreamWriter(fileOutName))
            {

                file.WriteLine(sbOutFile.ToString());
            }
            //Press enter to continue 
            Console.WriteLine("Press enter to continue !");
            Console.ReadLine();
        }


    }
}