獲取計算機硬盤序列號用途很多,在網上找到了一個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直接使用吧,哈哈~
1、網上的半瓶子醋很多(包括我),當然,百度更多。GetVolumeInformation是獲取分區序列號,不是物理序列號,重裝系統、格式化硬盤就會變,甚至用軟件都能修改。還有一種WMI方法,不過不保險(有的硬盤ID前面有空字符)。比較保險的是DeviceIoControl函數,代碼較長。
2、如果樓主喜歡那個GetVolumeInformation,那可以繼續用下去,當我沒回帖。如果想獲取真正的物理序列號,可以試試下面代碼。
uses Windows, SysUtils;
type
TIDERegs = packed record
bFeaturesReg: Byte;
bSectorCountReg: Byte;
bSectorNumberReg: Byte;
bCylLowReg: Byte;
bCylHighReg: Byte;
bDriveHeadReg: Byte;
bCommandReg: Byte;
bReserved: Byte;
end;
TSendCmdInParams = packed record
cBufferSize: DWORD;
irDriveRegs: TIDERegs;
bDriveNumber: Byte;
bReserved: array[0..2] of Byte;
dwReserved: array[0..3] of DWORD;
bBuffer: array[0..0] of Byte;
end;
PIdSector = ^TIdSector;
TIdSector = packed record
wGenConfig: Word;
wNumCyls: Word;
wReserved: Word;
wNumHeads: Word;
wBytesPerTrack: Word;
wBytesPerSector: Word;
wSectorsPerTrack: Word;
wVendorUnique: array[0..2] of Word;
sSerialNumber: array[0..19] of Char;
wBufferType: Word;
wBufferSize: Word;
wECCSize: Word;
sFirmwareRev: array[0..7] of Char;
sModelNumber: array[0..39] of Char;
wMoreVendorUnique: Word;
wDoubleWordIO: Word;
wCapabilities: Word;
wReserved1: Word;
wPIOTiming: Word;
wDMATiming: Word;
wBS: Word;
wNumCurrentCyls: Word;
wNumCurrentHeads: Word;
wNumCurrentSectorsPerTrack: Word;
ulCurrentSectorCapacity: DWORD;
wMultSectorStuff: Word;
ulTotalAddressableSectors: DWORD......余下全文>>
給我郵件,我給你發個
mapsapi@qq.com