获取计算机硬盘序列号用途不少,在网上找到了一个C++的源代码DriveInfoEx(点这里查看)。很是好的一个DLL,.NET项目能够直接引用,并且源代码里有示例。git
但这个DLL在Win7非管理员权限下,没法获取硬盘序列号,因此我就完善了一下这个DLL,让其支持Win7 非管理员。github
https://github.com/Xiongpq/DriveInfoExFullui
编译时请注意this
源代码内的一些方法,在VC90里已经被系统直接支持,因此就不用再重复定义,否则编译不过,因此若是在VC90及大于VC90平台编译的话,须要加一个“VC90”的“预处理器定义”。spa
代码中我作了判断,若是预约义了“VC90”就不会定义一些方法。在VC80及小于VC80平台编译的话,不用作这个设置。code
DriveInfoExFull/DriveInfoEx/bin 目录下有已经编译好的DLL,这两个DLL支持.NET Framework 2.0ip
原做者的代码已经能很好支持非管理员权限下的硬盘序列号获取,我就再也不分析原来的代码,只是大概说下我修改的内容。get
ReadPhysicalDriveInNTWithZeroRights这个方法被原做者注释掉了,不知道什么缘由,这个方法就是在没有权限的状况下获取硬盘序列号。it
用这个方法若是找到的硬盘编号知足要求就添加到m_serizalNoVec中,这是一个vector<char*>io
而后在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直接使用吧,哈哈~