程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> C# >> C#入門知識 >> C#通過WMI操作遠程機器

C#通過WMI操作遠程機器

編輯:C#入門知識

在幾天前,我對於WMI還是一竅不通的,連它是什麼的縮寫都不知道。。。但項目用到這方面的知識,於是便把這幾天學的到東西跟大家共享一下。

 

以下是來自MSDN對於WMI描述的原文:

 

Windows Management Instrumentation (WMI) is the infrastructure for management data

and operations on Windows-based operating systems. You can write WMI scripts or

applications to automate administrative tasks on remote computers but WMI also supplies

management data to other parts of the operating system and products.

大意是說,WMI(Windows管理規范)是用來對Windows進行數據和操作管理的基本工具。可以寫些WMI腳本或者程序來自動地在遠程機器上執行一些任務,同時,WMI也提供一些管理數據的功能。(這不廢話嘛,說了跟沒說一樣)

 

那我來說一下我的理解:WMI其實就是一種對Windows進行管理的工具,它的管理范圍不限於本機,只要是能連接上的裝的Windows的並且開了WMI服務的機器它都可以管理。這個管理的范圍有點廣,包括查詢機器的硬盤、注冊表信息,控制機器執行一些程序,共享機器的某些文件或文件夾。。。(其實從比較邪惡的角度來看,WMI是一種很危險的技術。。。)

 

廢話少說,言歸正傳,既然要操縱遠程機器,首先就要連接到遠程機器,關鍵代碼如下:

 

ConnectionOptions ops = new ConnectionOptions();  // 新建連接選項ops.Username = "Administrator";  // 遠程機器的用戶名,假設為Administratorops.Password = "123456";         // 對應用戶名的密碼ops.EnablePrivileges = true;string address = "127.0.0.1";    // 遠程機器IP地址ManagementScope scope = new ManagementScope(@"\\" + address + @"\root\cimv2", ops);  // 新建一個到遠程機器的連接scope.Connect();  // 進行連接

 

好了,如果用戶名、密碼、IP地址正確的話,就可以連上了。細心的童鞋可能會問,上面連接中的"\root\cimv2"是神馬?好吧,這是一個命名空間,在連接時要指定連接到哪個命令空間。其實這和編程語言中的命令空間有點類似,假設F1功能在命令空間N1下,F2在N2下,如果你連接到N2,那麼你能使用N2中的F2卻不能使用N1中的F1,因為連接在N2空間而不在N1空間。那為什麼這裡要連接"<address>\root\cimv2"空間呢?這是因為Windows常用的管理功能基本都在這個空間下(對注冊表的操作類StdRegProv在這個空間下有,在"<address>\root\DEFAULT"下面也有,但某些版本的Windows只存在於DEFAULT空間,所以對注冊表進行操作時建議連接到DEFAULT空間)。

 

連接了,就可以干些事情了。那怎麼控制遠程電腦呢?WMI提供了一系列的類,類中有相應的方法,通過對這些方法進行調用,就可以完成自己的想法。下面看一個實例:

 

if(scope.IsConnected) {  // 先判斷連接是不是成功    ObjectGetOptions obj = new ObjectGetOptions(null, System.TimeSpan.MaxValue, true);  // 對象接收選項    ManagementClass registry = new ManagementClass(scope, new ManagementPath("StdRegProv"), obj);  // 生成遠程的StdRegProv對象    ManagementBaseObject inParams = registry.GetMethodParameters("GetStringValue");  // 獲得StdRegProv的GetStringValue()方法的輸入參數    inParams["hDefKey"] = 0x80000002;            // 代表HKEY_LOCAL_MACHINE    inParams["sSubKeyName"] = "SOFTWARE\7-Zip";  // 注冊表的鍵    inParams["sValueName"] = "Path";             // 注冊表值的名字    ManagementBaseObject outParams = registry.InvokeMethod("GetStringValue", inParams, null);  // 根據inParams中的參數調用GetStringValue()方法    if((uint)outParams.Properties["ReturnValue"].Value == 0) {  // 如果返回0表明方法執行成功        Console.WriteLine((string)outParams.Properties["sValue"].Value);    } else {        Console.WriteLine("GetStringValue() failed.");    }}

 

上面的代碼先遠程創建了一個StdRegProv類的對象,再獲得它的GetStringValue()方法參數的名字等信息,再對其進行賦值,再對已賦值的參數調用GetStringValue()方法,方法返回值在返回參數中用"ReturnValue"標識,另外一些類似C#的ref關鍵字標明的參數返回值用其定義的名字標識。看起來很繞吧?其實看看StdRegProv類的GetStringValue()方法聲明就什麼都明白了:

 

uint32 GetStringValue(  [in]   uint32 hDefKey = 2147483650,  [in]   string sSubKeyName,  [in]   string sValueName,  [out]  string sValue);

 

很清楚吧?[in]標識的參數是要輸入傳遞給方法的,用[out]標識的參數是要輸出的,它們的名字與上面代碼中的輸入輸出參數一一對應。

 

好了,解釋一下上面代碼的功能:從注冊表"HKEY_LOCAL_MACHINE\SOFTWARE\7-Zip"鍵下讀取Path的值,然後顯示出來,如果安裝了7-Zip,則執行會成功,如果沒安裝,注冊表相應的鍵都不存在,自然會執行失敗,那麼這段代碼的作用就可以用來判斷遠程機器上有沒有安裝7-Zip。

 

那hDefKey這個參數是什麼樣一種情況呢?MSDN上有如下說明:

 

HKEY_CLASSES_ROOT (2147483648 (0x80000000))HKEY_CURRENT_USER (2147483649 (0x80000001))HKEY_LOCAL_MACHINE (2147483650 (0x80000002))HKEY_USERS (2147483651 (0x80000003))HKEY_CURRENT_CONFIG (2147483653 (0x80000005))HKEY_DYN_DATA (2147483654 (0x80000006))

 

這就是注冊表各個根對應的無符號32位數的由來,其定義在Winreg.h中。

 

這篇隨筆的標題是說操作遠程機器,但說了半天,好像一直在解釋如何操作遠程Windows機器的注冊表,而且還只是在解釋如何讀,這離標題差得還有點遠吧?是的,但我不想一一去寫如何操作硬盤,如何共享,如何遠程創建進程,因為功能太多了,要真全寫出來的話,那個啥,是吧(PS:其實是我不可能全部寫出來^_^)。本篇只是解釋一下原理和使用C#的初步實現,起一個拋磚引玉的作用,因為其它功能的實現是大同小異的,都是通過遠程創建WMI對象然後執行其方法,例如使用Win32_Process類的Create()方法可以在遠程機器上創建一個進程,使用Win32_Share類可以進行共享。。。所以,需要什麼功能,去MSDN吧,它知道的可比我多多了(至少這篇隨筆是我在MSDN上這裡抄點,那裡復制點寫出來的^_^)。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved