原文地址:
http://www.cnblogs.com/SunYu/archive/2010/04/29/1723977.htmlcodeproject:
http://www.codeproject.com/KB/system/HwDetect.aspx
簡介
現(xiàn)在對于IT的安全來說,熱插撥設(shè)備是個(gè)很大的威脅。在這篇文章中,我將試著開發(fā)一個(gè)用戶應(yīng)用程序來檢測本機(jī)系統(tǒng)上的設(shè)備改變。例如:插入一個(gè)USB設(shè)備、Ipod、USB無線網(wǎng)卡等等。這個(gè)程序同樣也可以停用任何支持插拔的設(shè)備。在文章的后面,我會(huì)簡述一下程序的工作原理和它的局限性。
怎么來檢測硬件設(shè)備的改變?
事實(shí)上,Windows操作系統(tǒng)會(huì)對上層程序發(fā)送WM_DEVICECHANGE消息來通知設(shè)備的改變。我們所要作的僅僅是添加一個(gè)句柄來處理這個(gè)事件。
Collapse
BEGIN_MESSAGE_MAP(CHWDetectDlg, CDialog)
// ... other handlers
ON_MESSAGE(WM_DEVICECHANGE, OnMyDeviceChange)
END_MESSAGE_MAP()
LRESULT CHWDetectDlg::OnMyDeviceChange(WPARAM wParam, LPARAM lParam)
{
// for more information, see MSDN help of WM_DEVICECHANGE
// this part should not be very difficult to understand
if ( DBT_DEVICEARRIVAL == wParam || DBT_DEVICEREMOVECOMPLETE == wParam ) {
PDEV_BROADCAST_HDR pHdr = (PDEV_BROADCAST_HDR)lParam;
switch( pHdr->dbch_devicetype ) {
case DBT_DEVTYP_DEVICEINTERFACE:
PDEV_BROADCAST_DEVICEINTERFACE pDevInf = (PDEV_BROADCAST_DEVICEINTERFACE)pHdr;
// do something...
break;
case DBT_DEVTYP_HANDLE:
PDEV_BROADCAST_HANDLE pDevHnd = (PDEV_BROADCAST_HANDLE)pHdr;
// do something...
break;
case DBT_DEVTYP_OEM:
PDEV_BROADCAST_OEM pDevOem = (PDEV_BROADCAST_OEM)pHdr;
// do something...
break;
case DBT_DEVTYP_PORT:
PDEV_BROADCAST_PORT pDevPort = (PDEV_BROADCAST_PORT)pHdr;
// do something...
break;
case DBT_DEVTYP_VOLUME:
PDEV_BROADCAST_VOLUME pDevVolume = (PDEV_BROADCAST_VOLUME)pHdr;
// do something...
break;
}
}
return 0;
}
然而默認(rèn)情況下,Windows操作系統(tǒng)發(fā)送WM_DEVICECHANGE有些限制:
1 只有頂層窗體的程序才能收到這個(gè)消息
2 僅僅串口、磁盤發(fā)生改變,才對每個(gè)程序廣播這個(gè)消息
的確不錯(cuò),至少你可以知道移動(dòng)U盤、移動(dòng)硬盤、光盤被安裝或彈出了,通過DEV_BROADCAST_VOLUME.dbcv_unitmask你也可以獲得其對應(yīng)的盤符。但實(shí)際上,你不知道底層處理的是哪個(gè)物理設(shè)備實(shí)際上被安裝到了系統(tǒng)中。
API:RegisterDeviceNotification()
所以,你不得不調(diào)用RegisterDeviceNotification()API來注冊其他類型的設(shè)備改變,或是你的程序僅僅是一個(gè)服務(wù)程序、沒有頂層窗體的程序。例如:如下的例子是用來注冊一個(gè)設(shè)備類型的接口的:
Collapse
1. DEV_BROADCAST_DEVICEINTERFACE NotificationFilter;
2. ZeroMemory( &NotificationFilter, sizeof(NotificationFilter) );
3. NotificationFilter.dbcc_size = sizeof(DEV_BROADCAST_DEVICEINTERFACE);
4. NotificationFilter.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE;
5. // assume we want to be notified with USBSTOR
6. // to get notified with all interface on XP or above
7. // ORed 3rd param with DEVICE_NOTIFY_ALL_INTERFACE_CLASSES and dbcc_classguid will be ignored
8. NotificationFilter.dbcc_classguid = GUID_DEVINTERFACE_USBSTOR;
9. HDEVNOTIFY hDevNotify = RegisterDeviceNotification(this->GetSafeHwnd(),
amp;NotificationFilter, DEVICE_NOTIFY_WINDOW_HANDLE);
10. if( !hDevNotify ) {
11. // error handling...
12. return FALSE;
13. }
請注意第8行,NotificationFilter.dbcc_classguid
關(guān)注的就是你關(guān)心的一類設(shè)備。
參考這個(gè)blog: Doron Holan's blog
一個(gè)支持即插即用的設(shè)備,有2個(gè)不同的GUID相關(guān),一個(gè)設(shè)備接口GUID, 一個(gè)是設(shè)備類GUID
設(shè)備類GUID:定義了廣泛意義上一類設(shè)備的GUID,如果你打開設(shè)備管理器[我的電腦右鍵—>設(shè)備管理器],默認(rèn)的是按照“類型”排列的,每一個(gè)“類型”就是一個(gè)設(shè)備類,同時(shí)每一個(gè)設(shè)備類有一個(gè)唯一的ID就是設(shè)備類GUID。設(shè)備GUID定義了此類設(shè)備的圖標(biāo)、默認(rèn)的安全設(shè)置、安裝屬性(例如用戶不能手動(dòng)安裝這類設(shè)備,而必須通過PNP來遍歷),以及其他的設(shè)置信息。設(shè)備類GUID沒有定義對應(yīng)的I/O接口(請參考術(shù)語表),而更像是設(shè)備的分組。我認(rèn)為一個(gè)比較好的例子是端口類。串口COM和并口LPT 都是端口類的一部分,但其各有各的I/O接口,而且彼此互不兼容.一個(gè)設(shè)備僅僅屬于一個(gè)設(shè)備類。我們可以通過設(shè)備驅(qū)動(dòng)的INF文件的開頭來查看該設(shè)備的設(shè)備類GUID。
設(shè)備接口GUID:定義了相互關(guān)聯(lián)I/O接口的GUID,每一個(gè)接口GUID的具體實(shí)例都支持基本的I/O設(shè)置。設(shè)備接口GUID也是對應(yīng)的驅(qū)動(dòng)程序基于PNP狀態(tài)來注冊、啟用、禁用設(shè)備。如果需要,一個(gè)設(shè)備甚至可以注冊多個(gè)同樣GUID的實(shí)例(假使每個(gè)都有相同的名字)[注:在實(shí)際的程序中,多次插拔USB口,確實(shí)會(huì)驅(qū)出相同的串口,例如port12,port12,port12…],盡管在現(xiàn)實(shí)世界中完全不需要這樣。一個(gè)簡單的I/O關(guān)聯(lián)接口是鍵盤設(shè)備,每個(gè)鍵盤設(shè)備的接口GUID必須相同。
可以通過如下的注冊表路徑來查看當(dāng)前設(shè)備類GUID, 設(shè)備接口GUID:
- \\HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Class
- \\HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\DeviceClasses
常用設(shè)備的接口GUID如下:
設(shè)備接口名稱
|
GUID
|
USB Raw Device/USB設(shè)備
|
{a5dcbf10-6530-11d2-901f-00c04fb951ed}
|
Disk Device/磁盤設(shè)備
|
{53f56307-b6bf-11d0-94f2-00a0c91efb8b}
|
Network Card/網(wǎng)卡
|
{ad498944-762f-11d0-8dcb-00c04fc3358c}
|
Human Interface Device (HID)/人機(jī)界面設(shè)備
|
{4d1e55b2-f16f-11cf-88cb-001111000030}
|
Palm/手持設(shè)備
|
{784126bf-4190-11d4-b5c2-00c04f687a67}
|
DEV_BROADCAST_DEVICEINTERFACE的解碼
如下是修改處理捕獲對應(yīng)事件的函數(shù):
Collapse
LRESULT CHWDetectDlg::OnMyDeviceChange(WPARAM wParam, LPARAM lParam)
{
....
....
if ( DBT_DEVICEARRIVAL == wParam || DBT_DEVICEREMOVECOMPLETE == wParam )
{
PDEV_BROADCAST_HDR pHdr = (PDEV_BROADCAST_HDR)lParam;
switch( pHdr->dbch_devicetype )
{
case DBT_DEVTYP_DEVICEINTERFACE:
PDEV_BROADCAST_DEVICEINTERFACE pDevInf = (PDEV_BROADCAST_DEVICEINTERFACE)pHdr;
UpdateDevice(pDevInf, wParam);
break;
....
....
}
從MSDN中,我們知道
Collapse
typedef struct _DEV_BROADCAST_DEVICEINTERFACE {
DWORD dbcc_size;
DWORD dbcc_devicetype;
DWORD dbcc_reserved;
GUID dbcc_classguid;
TCHAR dbcc_name[1];
} DEV_BROADCAST_DEVICEINTERFACE *PDEV_BROADCAST_DEVICEINTERFACE;
我們似乎可以通過dbcc_name知道那個(gè)設(shè)備安裝到了當(dāng)前系統(tǒng)。J,答案是不對,dbcc_name僅僅是操作系統(tǒng)內(nèi)部使用來做為ID的,其實(shí)不易讀的,例如下面的這個(gè)dbcc_name:
\\?\USB#Vid_04e8&Pid_503b#0002F9A9828E0F06#{a5dcbf10-6530-11d2-901f-00c04fb951ed}
- \\?\USB: USB 意思是這是一個(gè)USB設(shè)備類
- Vid_04e8&Pid_053b:
Vid
/Pid
是一個(gè)廠商ID和產(chǎn)品ID(但這是由設(shè)備類指定的,USB設(shè)備類使用VID/PID,不同的設(shè)備類使用不同的命名約定)
- 002F9A9828E0F06: 不清楚是怎么生成的,是唯一設(shè)備ID
- {a5dcbf10-6530-11d2-901f-00c04fb951ed}:設(shè)備接口類GUID
現(xiàn)在,我們來解出設(shè)備描述信息或是設(shè)備別名,有2種辦法:
1 直接讀注冊表, \\HKLM\SYSTEM\CurrentControlSet\Enum\USB\Vid_04e8&Pid_503b\0002F9A9828E0F06
2 使用 SetupDiXxx 系列API
API:SetupDiXxx()
Windows定義了一組API,讓用戶通過編程的辦法來獲取對應(yīng)的硬件設(shè)備信息。例如,我們可以通過dbcc_name來獲得設(shè)備描述信息或是設(shè)備別名。下面是這個(gè)辦法都具體步驟:
1 首先通過SetupDiGetClassDevs()來獲得設(shè)備信息集 HDEVINFO,這個(gè)操作等同于是一個(gè)獲取目錄句柄的過程。
2 接著使用SetupDiEnumDeviceInfo()來遍歷出這個(gè)設(shè)備信息集內(nèi)的所有設(shè)備,這個(gè)操作等同于把目錄列表的過程。對于每個(gè)遍歷出的,我們可以獲得SP_DEVINFO_DATA,這個(gè)等同于是文件句柄。
3 在上面的枚舉過程中,使用SetupDiGetDeviceInstanceId()來讀取每個(gè)設(shè)備的實(shí)例ID,這個(gè)操作等同于是讀文件的屬性,一個(gè)設(shè)備的實(shí)例ID類似這個(gè):”USB\Vid_04e8&Pid_503b\0002F9A9828E0F06”,和dbcc_name非常像。
4 如果設(shè)備的實(shí)例ID等同于dbcc_name,則通過SetupDiGetDeviceRegistryProperty()來獲取設(shè)備描述信息或是設(shè)備別名信息。
程序如下:
Collapse
void CHWDetectDlg::UpdateDevice(PDEV_BROADCAST_DEVICEINTERFACE pDevInf, WPARAM wParam)
{
// dbcc_name:
// \\?\USB#Vid_04e8&Pid_503b#0002F9A9828E0F06#{a5dcbf10-6530-11d2-901f-00c04fb951ed}
// convert to
// USB\Vid_04e8&Pid_503b\0002F9A9828E0F06
ASSERT(lstrlen(pDevInf->dbcc_name) > 4);
CString szDevId = pDevInf->dbcc_name+4;
int idx = szDevId.ReverseFind(_T('#'));
ASSERT( -1 != idx );
szDevId.Truncate(idx);
szDevId.Replace(_T('#'), _T('\\'));
szDevId.MakeUpper();
CString szClass;
idx = szDevId.Find(_T('\\'));
ASSERT(-1 != idx );
szClass = szDevId.Left(idx);
// if we are adding device, we only need present devices
// otherwise, we need all devices
DWORD dwFlag = DBT_DEVICEARRIVAL != wParam
? DIGCF_ALLCLASSES : (DIGCF_ALLCLASSES | DIGCF_PRESENT);
HDEVINFO hDevInfo = SetupDiGetClassDevs(NULL, szClass, NULL, dwFlag);
if( INVALID_HANDLE_VALUE == hDevInfo )
{
AfxMessageBox(CString("SetupDiGetClassDevs(): ")
+ _com_error(GetLastError()).ErrorMessage(), MB_ICONEXCLAMATION);
return;
}
SP_DEVINFO_DATA* pspDevInfoData =
(SP_DEVINFO_DATA*)HeapAlloc(GetProcessHeap(), 0, sizeof(SP_DEVINFO_DATA));
pspDevInfoData->cbSize = sizeof(SP_DEVINFO_DATA);
for(int i=0; SetupDiEnumDeviceInfo(hDevInfo,i,pspDevInfoData); i++)
{
DWORD DataT ;
DWORD nSize=0 ;
TCHAR buf[MAX_PATH];
if ( !SetupDiGetDeviceInstanceId(hDevInfo, pspDevInfoData, buf, sizeof(buf), &nSize) )
{
AfxMessageBox(CString("SetupDiGetDeviceInstanceId(): ")
+ _com_error(GetLastError()).ErrorMessage(), MB_ICONEXCLAMATION);
break;
}
if ( szDevId == buf )
{
// device found
if ( SetupDiGetDeviceRegistryProperty(hDevInfo, pspDevInfoData,
SPDRP_FRIENDLYNAME, &DataT, (PBYTE)buf, sizeof(buf), &nSize) ) {
// do nothing
} else if ( SetupDiGetDeviceRegistryProperty(hDevInfo, pspDevInfoData,
SPDRP_DEVICEDESC, &DataT, (PBYTE)buf, sizeof(buf), &nSize) ) {
// do nothing
} else {
lstrcpy(buf, _T("Unknown"));
}
// update UI
// .....
// .....
break;
}
}
if ( pspDevInfoData ) HeapFree(GetProcessHeap(), 0, pspDevInfoData);
SetupDiDestroyDeviceInfoList(hDevInfo);
}
禁用設(shè)備
假使你有一個(gè)正確的HDEVINFO和SP_DEVINFO_DATA(實(shí)際上,我們保持dbcc_name座位樹節(jié)點(diǎn)的tag,當(dāng)右鍵單擊某一個(gè)節(jié)點(diǎn)的時(shí)候,可以通過調(diào)用SetupDiGetClassDevs和SetupDiEnumDeviceInfo來獲得所需東西),按照如下的步驟即可禁用一個(gè)設(shè)備:
1 給SP_PROPCHANGE_PARAMS結(jié)構(gòu)體賦上正確的值
2 把上面賦完值的SP_PROPCHANGE_PARAMS作為參數(shù)傳入到SetupDiSetClassInstallParams()
3 調(diào)用SetupDiCallClassInstaller(),傳遞參數(shù)DIF_PROPEFRTYCHANGE
實(shí)際上,DIF也是按位做與運(yùn)算后兼容的,你也可以去傳遞不同的DIF參數(shù)來調(diào)用SetupDiSetClassInstallParams()。 更多信息,請參考MSDN”Handling DIF Codes”
Collapse
SP_PROPCHANGE_PARAMS spPropChangeParams ;
spPropChangeParams.ClassInstallHeader.cbSize = sizeof(SP_CLASSINSTALL_HEADER);
spPropChangeParams.ClassInstallHeader.InstallFunction = DIF_PROPERTYCHANGE ;
spPropChangeParams.Scope = DICS_FLAG_GLOBAL ;
spPropChangeParams.HwProfile = 0; // current hardware profile
spPropChangeParams.StateChange = DICS_DISABLE
if( !SetupDiSetClassInstallParams(hDevInfo, &spDevInfoData,
// note we pass spPropChangeParams as SP_CLASSINSTALL_HEADER
// but set the size as sizeof(SP_PROPCHANGE_PARAMS)
(SP_CLASSINSTALL_HEADER*)&spPropChangeParams, sizeof(SP_PROPCHANGE_PARAMS)) )
{
// handle error
}
else if(!SetupDiCallClassInstaller(DIF_PROPERTYCHANGE, hDevInfo, &spDevInfoData))
{
// handle error
}
else
{
// ok, show disable success dialog
// note, after that, the OS will post DBT_DEVICEREMOVECOMPLETE for the disabled device
}
附錄:
我使用這個(gè)程序,已經(jīng)多次測試了USB的無線網(wǎng)卡的,插入、拔出測試。
局限性:
1 明顯的,必須先運(yùn)行該程序,才能檢測硬件設(shè)備。例如:設(shè)備在操作系統(tǒng)啟動(dòng)前就已經(jīng)連接,或者在這個(gè)程序運(yùn)行前的連接都不會(huì)被檢測。但這個(gè)問題,可以通過保存當(dāng)前系統(tǒng)配置到遠(yuǎn)程計(jì)算機(jī)上,等啟動(dòng)完這個(gè)程序后再堅(jiān)持不同的配置來解決
2 我們可以禁用設(shè)備,換而言之這也是我們所有能做到。我們不能訪問設(shè)備底層控制。 我認(rèn)為可以通過重新用基于內(nèi)核的過濾驅(qū)動(dòng)來實(shí)現(xiàn),則可以解決這個(gè)問題。
原文地址:
http://blog.csdn.net/tongxuechen1982/archive/2008/05/26/2483123.aspx用C#做串口通訊很方便,因?yàn)閐otfx2.0已經(jīng)集成了Serial Port控件,此控件使用上比MSComm控件更簡單,當(dāng)然它也有一個(gè)小bug(RecievedBytesThreshold設(shè)置有時(shí)候不好使),但是這個(gè)問題很好解決,而做串口通訊最最基本的問題就是如何獲得目標(biāo)機(jī)器的要與之通訊的特定設(shè)備的特定com號(hào),有許多軟件在處理這個(gè)問題的時(shí)候都是要求用戶手動(dòng)去選擇對應(yīng)的串口號(hào),這多少有些不人性化,這篇文章就是介紹如何自動(dòng)獲得目標(biāo)機(jī)器對應(yīng)特定串口設(shè)備的串口號(hào),從而達(dá)到軟件與目標(biāo)設(shè)備的自動(dòng)通訊。
方法基本上是我前一篇文章的一個(gè)應(yīng)用,代碼如下(注意自己添加引用的命名空間)

/**//**//**//// <summary>
/// 通過vid,pid獲得串口設(shè)備號(hào)
/// </summary>
/// <param name="vid">vid</param>
/// <param name="pid">pid</param>
/// <returns>串口號(hào)</returns>
public static string GetPortNameFormVidPid(string vid, string pid)


{
Guid myGUID = Guid.Empty;
string enumerator = "USB";
try


{
IntPtr hDevInfo = HardWareLib.SetupDiGetClassDevs(ref myGUID, enumerator, IntPtr.Zero, HardWareLib.DIGCF_ALLCLASSES | HardWareLib.DIGCF_PRESENT);
if (hDevInfo.ToInt32() == HardWareLib.INVALID_HANDLE_VALUE)


{
throw new Exception("沒有該類設(shè)備");
}
HardWareLib.SP_DEVINFO_DATA deviceInfoData;//想避免在api中使用ref,就把structure映射成類
deviceInfoData = new HardWareLib.SP_DEVINFO_DATA();
deviceInfoData.cbSize = 28;//如果要使用SP_DEVINFO_DATA,一定要給該項(xiàng)賦值28=16+4+4+4
deviceInfoData.devInst = 0;
deviceInfoData.classGuid = System.Guid.Empty;
deviceInfoData.reserved = 0;
UInt32 i;
StringBuilder property = new StringBuilder(HardWareLib.MAX_DEV_LEN);
for (i = 0; HardWareLib.SetupDiEnumDeviceInfo(hDevInfo, i, deviceInfoData); i++)


{
// Console.Write(deviceInfoData.classGuid.ToString());
// HardWareOperation.SetupDiGetDeviceInstanceId(hDevInfo, deviceInfoData, porperty, (uint)porperty.Capacity, 0);
HardWareLib.SetupDiGetDeviceRegistryProperty(hDevInfo, deviceInfoData,
(uint)HardWareLib.SPDRP_.SPDRP_CLASS,
0, property, (uint)property.Capacity, IntPtr.Zero);
if (property.ToString().ToLower() != "ports") continue;//首先看看是不是串口設(shè)備(有些USB設(shè)備不是串口設(shè)備)
HardWareLib.SetupDiGetDeviceRegistryProperty(hDevInfo, deviceInfoData,
(uint)HardWareLib.SPDRP_.SPDRP_HARDWAREID,
0, property, (uint)property.Capacity, IntPtr.Zero);
if (!(property.ToString().ToLower().Contains(vid.ToLower())
&& property.ToString().ToLower().Contains(pid.ToLower()))) continue;//找到對應(yīng)于vid&pid的設(shè)備
HardWareLib.SetupDiGetDeviceRegistryProperty(hDevInfo, deviceInfoData,
(uint)HardWareLib.SPDRP_.SPDRP_FRIENDLYNAME,
0, property, (uint)property.Capacity, IntPtr.Zero);
break;

}
HardWareLib.SetupDiDestroyDeviceInfoList(hDevInfo);//記得用完釋放相關(guān)內(nèi)存
string friendlyName = property.ToString();
string pattern=@"(COM[1-9][0-9]?)$";//friendlyName一般形式為以(COMn)結(jié)尾,n為1-99
if (Regex.IsMatch(friendlyName, pattern, RegexOptions.IgnoreCase))


{
string portName=Regex.Match(friendlyName, pattern, RegexOptions.IgnoreCase).Value;

return portName.Trim(new char[] 
{ '(', ')' });
}
return null;
}
catch (Exception ex)


{
MessageBox.Show(ex.Message);
return null;
}
}
HardWareLib.cs(也就是前一篇文章的一個(gè)類)
HardWareLib.cs(也就是前一篇文章的一個(gè)類) using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;

namespace ForGeneralUse



{
public class HardWareLib


{

/**//**//**//// <summary>
/// 設(shè)備的各項(xiàng)屬性,注意有些屬性是不通用的,例如SPDRP_FRIENDLYNAME只適用于端口設(shè)備
/// </summary>
public enum SPDRP_


{
SPDRP_DEVICEDESC = (0x00000000), // DeviceDesc (R/W)
SPDRP_HARDWAREID = (0x00000001), // HardwareID (R/W)
SPDRP_SERVICE = (0x00000004), // Service (R/W)
SPDRP_CLASS = (0x00000007), // Class (R--tied to ClassGUID)
SPDRP_CLASSGUID = (0x00000008), // ClassGUID (R/W)
SPDRP_DRIVER = (0x00000009), // Driver (R/W)
SPDRP_CONFIGFLAGS = (0x0000000A), // ConfigFlags (R/W)
SPDRP_MFG = (0x0000000B), // Mfg (R/W)
SPDRP_FRIENDLYNAME = (0x0000000C), // FriendlyName (R/W)
SPDRP_PHYSICAL_DEVICE_OBJECT_NAME = (0x0000000E), // PhysicalDeviceObjectName (R)
SPDRP_CAPABILITIES = (0x0000000F), // Capabilities (R)
SPDRP_REMOVAL_POLICY_HW_DEFAULT = (0x00000020), // Hardware Removal Policy (R)
SPDRP_INSTALL_STATE = (0x00000022), // Device Install State (R)
}
public const int DIGCF_ALLCLASSES = (0x00000004);
public const int DIGCF_DEVICEINTERFACE = 0x00000010;
public const int DIGCF_PRESENT = (0x00000002);
public const int INVALID_HANDLE_VALUE = -1;
public const int MAX_DEV_LEN = 1000;


/**//**//**//// <summary>
/// 獲取一個(gè)指定類別或全部類別的所有已安裝設(shè)備的信息
/// </summary>
/// <param name="gClass">該類別對應(yīng)的guid</param>
/// <param name="iEnumerator">類別名稱(在HKLMSYSTEMCurrentControlSetEnum內(nèi)獲取)</param>
/// <param name="hParent">應(yīng)用程序定義的窗口句柄</param>
/// <param name="nFlags">獲取的模式</param>
/// <returns>設(shè)備信息集合的句柄</returns>
[DllImport("setupapi.dll", SetLastError = true, CharSet = CharSet.Auto)]
public static extern IntPtr SetupDiGetClassDevs(ref Guid gClass, String enumerator, IntPtr hParent, UInt32 nFlags);


/**//**//**//// <summary>
/// 獲得該設(shè)備的設(shè)備范例ID
/// </summary>
/// <param name="DeviceInfoSet">設(shè)備信息集合</param>
/// <param name="DeviceInfoData">表示該設(shè)備</param>
/// <param name="DeviceInstanceId">設(shè)備范例ID(輸出)</param>
/// <param name="DeviceInstanceIdSize">該ID所占大小(字節(jié))</param>
/// <param name="RequiredSize">需要多少字節(jié)</param>
/// <returns>是否成功</returns>
[DllImport("setupapi.dll", SetLastError = true)]
public static extern bool SetupDiGetDeviceInstanceId(IntPtr DeviceInfoSet,
HardWareLib.SP_DEVINFO_DATA DeviceInfoData,
StringBuilder DeviceInstanceId,
UInt32 DeviceInstanceIdSize,
UInt32 RequiredSize);


/**//**//**//// <summary>
/// 枚舉指定設(shè)備信息集合的成員,并將數(shù)據(jù)放在SP_DEVINFO_DATA中
/// </summary>
/// <param name="lpInfoSet">設(shè)備信息集合句柄</param>
/// <param name="dwIndex">元素索引</param>
/// <param name="devInfoData">表示一個(gè)設(shè)備(作為輸出)</param>
/// <returns>是否成功</returns>
[DllImport("setupapi.dll", SetLastError = true)]
public static extern bool SetupDiEnumDeviceInfo(IntPtr lpInfoSet, UInt32 dwIndex, SP_DEVINFO_DATA devInfoData);


/**//**//**//// <summary>
/// 獲取指定設(shè)備的屬性
/// </summary>
/// <param name="lpInfoSet">設(shè)備信息集合</param>
/// <param name="DeviceInfoData">表示該設(shè)備</param>
/// <param name="Property">表示要獲取哪項(xiàng)屬性</param>
/// <param name="PropertyRegDataType">注冊類型</param>
/// <param name="PropertyBuffer">屬性(輸出)</param>
/// <param name="PropertyBufferSize">存儲(chǔ)屬性的字節(jié)大小</param>
/// <param name="RequiredSize">需要的字節(jié)大小</param>
/// <returns>是否成功</returns>
[DllImport("setupapi.dll", SetLastError = true)]
public static extern bool SetupDiGetDeviceRegistryProperty(IntPtr lpInfoSet,
SP_DEVINFO_DATA DeviceInfoData,
UInt32 Property,
UInt32 PropertyRegDataType,
StringBuilder PropertyBuffer,
UInt32 PropertyBufferSize,
IntPtr RequiredSize);


/**//**//**//// <summary>
/// 銷毀一個(gè)設(shè)備信息集合,并且釋放所有關(guān)聯(lián)的內(nèi)存
/// </summary>
/// <param name="lpInfoSet">設(shè)備信息集合</param>
/// <returns></returns>
[DllImport("setupapi.dll", SetLastError = true)]
public static extern bool SetupDiDestroyDeviceInfoList(IntPtr lpInfoSet);


/**//**//**//// <summary>
/// 設(shè)備信息數(shù)據(jù)
/// </summary>
[StructLayout(LayoutKind.Sequential)]
public class SP_DEVINFO_DATA


{
public int cbSize;//本結(jié)構(gòu)的大小(字節(jié)表示)
public Guid classGuid;//本結(jié)構(gòu)所表示的設(shè)備的GUID
public int devInst;//設(shè)備句柄
public ulong reserved;//沒用
};
}
}
posted on 2010-09-13 21:27
漂漂 閱讀(11385)
評論(0) 編輯 收藏 引用 所屬分類:
深入vc++ 、
c#開發(fā)