简体   繁体   English

如何读取远程注册表项?

[英]How to Read Remote Registry Keys?

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或其他什么?

You can achieve this through WMI, although I think you can also achieve it via the same mechanism (ie 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 性SecurityPermission

and

RegistryPermission RegistryPermission的

classes in the System.Security.Permissions namespace. System.Security.Permissions命名空间中的类。

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()方法但是它要求我更改dest计算机上注册表中的权限。

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. 我还发现,我可以使用WMI获得相同的信息,而无需修改权限。 Here is the code with 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);
}

PS I am calling the GetStringValue() method in the loop as I know all the values are strings. PS我在循环中调用GetStringValue()方法,因为我知道所有的值都是字符串。 If there are multiple data types you would need to read the datatype from the Types output parameter of the EnumValues method. 如果有多种数据类型,则需要从EnumValues方法的Types输出参数中读取数据类型。

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. 代码正在生产和测试中。

The win32 API allows you to specify a computer name through RegConnectRegistry . win32 API允许您通过RegConnectRegistry指定计算机名称。 I'm not sure that the .NET wrappers exposes this. 我不确定.NET包装器会暴露这个。 You can also use WMI as you mentioned. 您也可以按照提到的那样使用WMI。

查找OpenRemoteBaseKey()。

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 :] 奇迹般有效 :]

Easy example in c# installed programs via windows registry (remote: OpenRemoteBaseKey) 通过Windows注册表安装程序的简单示例(远程: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();
        }


    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM