2009-10-14 3 views
8

Мне нужно уметь считывать значения в определенном ключе реестра из списка удаленных компьютеров. я могу сделать это локально с помощью следующего кодаКак читать удаленные ключи реестра?

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()); 
     } 

, но я не знаю, как получить ту же информацию для удаленного компьютера. Я даже использую правильный подход, или я должен смотреть на WMI или что-то еще?

+1

Вы считали WMI? –

ответ

12

Вы можете добиться этого через WMI, хотя я думаю, что вы также можете достичь этого через тот же механизм (то есть классы пространства имен Microsoft.Win32), которые вы используете в настоящее время.

Вы должны смотреть в:

OpenRemoteBaseKey Method

Ссылка выше приведены примеры. Это должно быть так же просто, как что-то вроде:

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

Примечание, однако, что будет там будет с точки зрения безопасности при открытии удаленных ключей реестра, так что вы, возможно, потребуется, чтобы гарантировать, что у вас есть соответствующие разрешения безопасности, чтобы сделать это , Для этого, вы будете хотеть смотреть в:

SecurityPermission

и

RegistryPermission

классы в System.Security.Permissions пространстве имен.

+1

принял это как ответ и поместил больше информации о том, как я использовал его для решения моей проблемы в ответе ниже. – etoisarobot

1

API win32 позволяет указать имя компьютера через RegConnectRegistry. Я не уверен, что обертки .NET предоставляют это. Вы также можете использовать WMI, как вы упомянули.

1

Посмотрите OpenRemoteBaseKey().

9

Я обнаружил, что, как показал CraigTP, использование метода OpenRemoteBaseKey() потребовало от меня изменить разрешения в реестре на компьютерах с ограниченными правами.

Вот код, который я написал, который работал, когда я сменил разрешения.

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()); 
} 

Я также обнаружил, что могу получить такую ​​же информацию с помощью 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. Я вызываю метод GetStringValue() в цикле, поскольку я знаю, что все значения являются строками. Если существует несколько типов данных, вам нужно будет прочитать тип данных из выходного параметра Types метода EnumValues.

+0

Какие разрешения вы изменили, так что «OpenRemoteBaseKey» работал? Благодаря! – boboes

1

Комментарии к моему блогу просили меня опубликовать мое решение по переполнению стека, так что вот оно.

How to authenticate and access the registry remotely using C#

Это в основном так же, как ответ CraigTP, но она включает в себя хороший класс для проверки подлинности на удаленном устройстве.

И код в стадии производства и испытания.

1

Это решение, которое я пошел с в конце концов:

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); 
      } 
     } 
    } 
} 

работает как шарм:]

1

Легкий пример в C# установленных программ с помощью реестра Windows (Remote: 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(); 
     } 


    } 
} 
Смежные вопросы