標籤:des style http color os io 使用 ar for
概述:
擷取電腦硬碟序號用途很多,在網上找到了一個C++的原始碼DriveInfoEx(點這裡查看)。非常好的一個DLL,.NET項目可以直接引用,而且原始碼裡有樣本。
但這個DLL在Win7非管理員權限下,無法擷取硬碟序號,所以我就完善了一下這個DLL,讓其支援Win7 非管理員。
原始碼:
https://github.com/Xiongpq/DriveInfoExFull
編譯時間請注意
原始碼內的一些方法,在VC90裡已經被系統直接支援,所以就不用再重複定義,不然編譯不過,所以如果在VC90及大於VC90平台編譯的話,需要加一個“VC90”的“前置處理器定義”。
代碼中我做了判斷,如果預定義了“VC90”就不會定義一些方法。在VC80及小於VC80平台編譯的話,不用做這個設定。
DriveInfoExFull/DriveInfoEx/bin 目錄下有已經編譯好的DLL,這兩個DLL支援.NET Framework 2.0
程式碼分析:
原作者的代碼已經能很好支援非管理員權限下的硬碟序號擷取,我就不再分析原來的代碼,只是大概說下我修改的內容。
ReadPhysicalDriveInNTWithZeroRights這個方法被原作者注釋掉了,不知道什麼原因,這個方法就是在沒有許可權的情況下擷取硬碟序號。
用這個方法如果找到的硬碟編號滿足要求就添加到m_serizalNoVec中,這是一個vector<char*>
然後在Load方法中判斷如果常規方法找到的硬碟個數為0,則將m_serizalNoVec中的硬碟資訊添加到結果中。這個只包括硬碟的序號,不包括大小等資訊。
下面就是這個方法:
int DiskInfo::ReadPhysicalDriveInNTWithZeroRights (void){ int done = FALSE; int drive = 0; for (drive = 0; drive < MAX_IDE_DRIVES; drive++) { HANDLE hPhysicalDriveIOCTL = 0; // Try to get a handle to PhysicalDrive IOCTL, report failure // and exit if can‘t. TCHAR driveName [256]; swprintf (driveName, L"\\\\.\\PhysicalDrive%d", drive); // Windows NT, Windows 2000, Windows XP - admin rights not required hPhysicalDriveIOCTL = CreateFile (driveName, 0, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL); if (hPhysicalDriveIOCTL != INVALID_HANDLE_VALUE) { STORAGE_PROPERTY_QUERY query; DWORD cbBytesReturned = 0; char buffer [10000]; memset ((void *) & query, 0, sizeof (query)); query.PropertyId = StorageDeviceProperty; query.QueryType = PropertyStandardQuery; memset (buffer, 0, sizeof (buffer)); if ( DeviceIoControl (hPhysicalDriveIOCTL, IOCTL_STORAGE_QUERY_PROPERTY, & query, sizeof (query), & buffer, sizeof (buffer), & cbBytesReturned, NULL) ) { STORAGE_DEVICE_DESCRIPTOR * descrip = (STORAGE_DEVICE_DESCRIPTOR *) & buffer; char* serialNumber = new char[1000]; strcpy (serialNumber, flipAndCodeBytes ( & buffer [descrip -> SerialNumberOffset])); int isAlnumAndSpace = TRUE; int isAllSpace = TRUE; int length=strlen(serialNumber); for(int i=0;i<length;i++){ if(!isalnum(serialNumber[i]) && serialNumber[i] != ‘ ‘){ isAlnumAndSpace=FALSE; break; } if(isAllSpace && serialNumber[i] != ‘ ‘){ isAllSpace=FALSE; } } //硬碟編號為字母、數字和空格,但不是純空格 if(isAlnumAndSpace && !isAllSpace){ m_serizalNoVec.push_back(serialNumber); } done=TRUE; } CloseHandle (hPhysicalDriveIOCTL); } } return done;}
INT Load() { DiskInfo& di = DiskInfo::GetDiskInfo(); UINT cnt = di.LoadDiskInfo(); for(UINT i=0; i < cnt; i++) this->Add(gcnew DriveInfoEx(i)); //判斷如果常規方法找到的硬碟為0,則將m_serizalNoVec中的硬碟資訊添加到結果中。 //這個只包括硬碟的序號,不包括大小等資訊。 if(cnt == 0){ UINT zeroRightCount = di.m_serizalNoVec.size(); for(UINT i=0; i < zeroRightCount; i++){ this->Add(gcnew DriveInfoEx(di.m_serizalNoVec[i])); } } return this->Count; };
還有一些其他的修改就不再詳細介紹,想瞭解的可以看看原始碼。
不想瞭解的,下載DLL直接使用吧,哈哈~
完善DriveInfoEx原始碼 擷取電腦硬碟序號