在需要對(duì)計(jì)算機(jī)進(jìn)行標(biāo)識(shí)的場(chǎng)景下,我們一般會(huì)選擇獲取一些硬件信息。然而CPU序列號(hào)可能有重復(fù)、網(wǎng)卡MAC地址和計(jì)算機(jī)名又能被輕易地修改,所以其中最可靠的應(yīng)該就是硬盤序列號(hào)了。Windows下硬盤序列號(hào)的獲取本身并不復(fù)雜,而關(guān)鍵在于如何在無(wú)需權(quán)限提升的情況下獲取到硬盤序列號(hào)。為了解決這個(gè)問(wèn)題,我也查了很多資料,基本上各大博客中貼出的都是需要權(quán)限提升的代碼。
 
最終,在DiskID32的源碼中,我找到了不提權(quán)獲取硬盤序列號(hào)的辦法。不過(guò)其源碼只能使用MBCS多字節(jié)字符集方式編譯,而無(wú)法使用Unicode字符集編譯,為此,我進(jìn)行了一些修改,使之兼容兩種方式。下面將經(jīng)過(guò)我修改、測(cè)試后的代碼貼出來(lái),供大家參考。
 
其中,獲取硬盤序列號(hào)的函數(shù)命名為GetHDSerial,該函數(shù)依賴flipAndCodeBytes函數(shù)。前者使用說(shuō)明如下:
 
 
#include <locale.h>
#include <tchar.h>
#include <windows.h>
#include <stdio.h>char * flipAndCodeBytes(
const char * str,
int pos,
int flip,
char * buf)
{
int i;
int j = 
0;
int k = 
0;buf[
0] = 
'\0';
if (pos <= 
0)
return buf;
if (!j){
char p = 
0;j = 
1;k = 
0;buf[k] = 
0;
for (i = pos; j && str[i] != 
'\0'; ++i){
char c = 
tolower(str[i]);
if (
isspace(c))c = 
'0';++p;buf[k] <<= 
4;
if (c >= 
'0' && c <= 
'9')buf[k] |= (
unsigned char)(c - 
'0');
else if (c >= 
'a' && c <= 
'f')buf[k] |= (
unsigned char)(c - 
'a' + 
10);
else{j = 
0;
break;}
if (p == 
2){
if (buf[k] != 
'\0' && !
isprint(buf[k])){j = 
0;
break;}++k;p = 
0;buf[k] = 
0;}}}
if (!j){j = 
1;k = 
0;
for (i = pos; j && str[i] != 
'\0'; ++i){
char c = str[i];
if (!
isprint(c)){j = 
0;
break;}buf[k++] = c;}}
if (!j){k = 
0;}buf[k] = 
'\0';
if (flip)
for (j = 
0; j < k; j += 
2){
char t = buf[j];buf[j] = buf[j + 
1];buf[j + 
1] = t;}i = j = -
1;
for (k = 
0; buf[k] != 
'\0'; ++k){
if (!
isspace(buf[k])){
if (i < 
0)i = k;j = k;}}
if ((i >= 
0) && (j >= 
0)){
for (k = i; (k <= j) && (buf[k] != 
'\0'); ++k)buf[k - i] = buf[k];buf[k - i] = 
'\0';}
return buf;
}
ULONG GetHDSerial(PCHAR pszIDBuff, 
int nBuffLen, 
int nDriveID)
{HANDLE hPhysicalDrive = INVALID_HANDLE_VALUE;ULONG ulSerialLen = 
0;__try{TCHAR szDriveName[
32];wsprintf(szDriveName, TEXT(
"\\\\.\\PhysicalDrive%d"), nDriveID);hPhysicalDrive = CreateFile(szDriveName, 
0,FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,OPEN_EXISTING, 
0, NULL);
if (hPhysicalDrive == INVALID_HANDLE_VALUE){__leave;}STORAGE_PROPERTY_QUERY query;DWORD cbBytesReturned = 
0;
static char local_buffer[
10000];
memset((
void *)&query, 
0, 
sizeof(query));query.PropertyId = StorageDeviceProperty;query.QueryType = PropertyStandardQuery;
memset(local_buffer, 
0, 
sizeof(local_buffer));
if (DeviceIoControl(hPhysicalDrive, IOCTL_STORAGE_QUERY_PROPERTY,&query,
sizeof(query),&local_buffer[
0],
sizeof(local_buffer),&cbBytesReturned, NULL)){STORAGE_DEVICE_DESCRIPTOR * descrip = (STORAGE_DEVICE_DESCRIPTOR *)& local_buffer;
char serialNumber[
1000];flipAndCodeBytes(local_buffer,descrip->SerialNumberOffset,
1, serialNumber);
if (
isalnum(serialNumber[
0])){ULONG ulSerialLenTemp = strnlen(serialNumber, nBuffLen - 
1);
memcpy(pszIDBuff, serialNumber, ulSerialLenTemp);pszIDBuff[ulSerialLenTemp] = NULL;ulSerialLen = ulSerialLenTemp;__leave;}}}__finally{
if (hPhysicalDrive != INVALID_HANDLE_VALUE){CloseHandle(hPhysicalDrive);}
return ulSerialLen;}
}
void GetAllHDSerial(
void)
{
const int MAX_IDE_DRIVES = 
16;
static char szBuff[
0x100];
for (
int nDriveNum = 
0; nDriveNum < MAX_IDE_DRIVES; nDriveNum++){ULONG ulLen = GetHDSerial(szBuff, 
sizeof(szBuff), nDriveNum);
if (ulLen > 
0){_tprintf(TEXT(
"第%d塊硬盤的序列號(hào)為:%hs\n"), nDriveNum + 
1, szBuff);}}
}
int main()
{setlocale(LC_ALL, 
"chs");GetAllHDSerial();system(
"pause");
return 0;
}
                            
總結(jié)
                            
                                以上是生活随笔為你收集整理的Windows下使用C++(Win32SDK)编程无需提权读取硬盘序列号(XP、Win7和Win10都可用)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
                            
                            
                                如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。