我根据Blacktempel在this帖子中提出的建议,使用DeviceIoControl函数检索物理硬盘的序列号。获得这个号码原则上工作正常,但我(仍然)有序列号格式的问题,因为它随着时间的推移不断变换。在正常用户或管理员运行程序之间,我在某些计算机上遇到了格式更改。
例如,我使用以下格式检索了一个数字:
WD-WCAZAF632086
当我第一次测试程序时,几周后看起来像:
2020202057202d4443575a414641333630323638
这仍然是相同的数字,只有字符已被十六进制代码替换并成对交换。我遇到过不同的格式,比如普通字符串,字符交换成双字符串。在其他值中,我需要检查此编号以验证软件许可证是否对某台计算机有效。有一个不稳定和未知的格式是令人讨厌的,如果格式改变为我还没有意识到的东西,我冒险软件许可证检查失败,尽管许可证仍然有效。
有谁知道如何以稳定的格式获取序列号,或者如何预测格式以便进行比较?
这是我用来检索第一个物理光盘序列号的最小C ++代码示例。我使用Visual Studio 2015构建它:
#include "stdafx.h"
#include "Windows.h"
#include <string>
#include <vector>
#include <iostream>
bool GetDeviceString(std::string &serialnumber)
{
HANDLE deviceHandle = CreateFileW(L"//./PhysicalDrive0", 0, FILE_SHARE_READ | FILE_SHARE_WRITE, nullptr, OPEN_EXISTING, 0, nullptr); // Get Handle to device
if (deviceHandle == INVALID_HANDLE_VALUE) // Check if Handle is valid
return false;
STORAGE_PROPERTY_QUERY query{};
query.PropertyId = StorageDeviceProperty;
query.QueryType = PropertyStandardQuery;
STORAGE_DESCRIPTOR_HEADER storageDescriptorHeader = { 0 };
DWORD dwBytesReturned;
if (!DeviceIoControl(deviceHandle, IOCTL_STORAGE_QUERY_PROPERTY,
&query, sizeof(STORAGE_PROPERTY_QUERY),
&storageDescriptorHeader, sizeof(STORAGE_DESCRIPTOR_HEADER), &dwBytesReturned, NULL))
{
}
// Alloc the output buffer
const DWORD dwOutBufferSize = storageDescriptorHeader.Size;
std::vector<BYTE> pOutBuffer(dwOutBufferSize,0);
if (!DeviceIoControl(deviceHandle, IOCTL_STORAGE_QUERY_PROPERTY,
&query, sizeof(STORAGE_PROPERTY_QUERY),
pOutBuffer.data(), dwOutBufferSize,
&dwBytesReturned, NULL))
{
// handle error, do cleanup and return
}
STORAGE_DEVICE_DESCRIPTOR* pDeviceDescriptor = (STORAGE_DEVICE_DESCRIPTOR*)pOutBuffer.data();
const DWORD dwSerialNumberOffset = pDeviceDescriptor->SerialNumberOffset;
if (dwSerialNumberOffset != 0)
{
// Finally, get the serial number
serialnumber = (char*)(pOutBuffer.data() + dwSerialNumberOffset);
}
}
int main()
{
std::string serialnumber;
if (GetDeviceString(serialnumber))
{
std::cout << "serial number of first disc: " << serialnumber << std::endl;
}
else
{
std::cout << "Failed!" << std::endl;
}
std::cin.ignore();
return 0;
}