windows 获取 磁盘 serialnum
#include <Windows.h>
#include <iostream>
#include <iomanip>
#include <ntddscsi.h>
int main() {
const wchar_t* drivePath = L"\\\\.\\PhysicalDrive0"; // 设置为磁盘的路径,根据需要更改
HANDLE hDevice = CreateFileW(
drivePath,
GENERIC_READ,
FILE_SHARE_READ | FILE_SHARE_WRITE,
nullptr,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
nullptr
);
if (hDevice == INVALID_HANDLE_VALUE) {
DWORD error = GetLastError();
std::cerr << "Error opening the device. Error code: " << error << std::endl;
return 1;
}
STORAGE_PROPERTY_QUERY storagePropertyQuery;
storagePropertyQuery.PropertyId = StorageDeviceProperty;
storagePropertyQuery.QueryType = PropertyStandardQuery;
STORAGE_DESCRIPTOR_HEADER storageDescriptorHeader;
DWORD bytesReturned;
if (DeviceIoControl(
hDevice,
IOCTL_STORAGE_QUERY_PROPERTY,
&storagePropertyQuery,
sizeof(storagePropertyQuery),
&storageDescriptorHeader,
sizeof(storageDescriptorHeader),
&bytesReturned,
nullptr
))
{
// 根据返回的 STORAGE_DESCRIPTOR_HEADER 获取设备信息
DWORD bufferSize = storageDescriptorHeader.Size;
std::vector<char> buffer(bufferSize);
if (DeviceIoControl(
hDevice,
IOCTL_STORAGE_QUERY_PROPERTY,
&storagePropertyQuery,
sizeof(storagePropertyQuery),
buffer.data(),
bufferSize,
&bytesReturned,
nullptr
))
{
STORAGE_DEVICE_DESCRIPTOR* deviceDescriptor = reinterpret_cast<STORAGE_DEVICE_DESCRIPTOR*>(buffer.data());
// 序列号在设备描述符的后面,跳过 VendorId 和 ProductId
wchar_t* serialNumber = reinterpret_cast<wchar_t*>(buffer.data() + deviceDescriptor->SerialNumberOffset);
std::wcout << L"Serial Number: " << serialNumber << std::endl;
}
else {
DWORD error = GetLastError();
std::cerr << "Error getting storage query property. Error code: " << error << std::endl;
}
}
else {
DWORD error = GetLastError();
std::cerr << "Error getting storage query property header. Error code: " << error << std::endl;
}
CloseHandle(hDevice);
return 0;
}
std::string get_disk_smart_serials(int index)
{
std::string ret;
char physical[256]{ 0 };
sprintf_s(physical, 256, "\\\\.\\PhysicalDrive%d", index);
HANDLE disk = CreateFileA(physical, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);
if (disk != INVALID_HANDLE_VALUE)
{
STORAGE_PROPERTY_QUERY query{ };
query.PropertyId = StorageDeviceProperty;
query.QueryType = PropertyStandardQuery;
const int b_size = 1024 * 10;
char* buf = new char[b_size];
if (buf)
{
memset(buf, 0, b_size);
DWORD r = 0;
BOOL status = DeviceIoControl(disk, IOCTL_STORAGE_QUERY_PROPERTY, &query, sizeof(query), buf, b_size, &r, NULL);
if (status)
{
STORAGE_DEVICE_DESCRIPTOR* descrip = (STORAGE_DEVICE_DESCRIPTOR*)buf;
if (descrip->SerialNumberOffset > 0)
{
std::string serial = buf + descrip->SerialNumberOffset;
serial.erase(std::remove_if(serial.begin(), serial.end(), [](unsigned char x) {return std::isspace(x); }), serial.end());
ret = serial;
}
}
delete[] buf;
}
CloseHandle(disk);
}
return ret;
}
// 打开设备对象的过程略去,得到句柄hDrive
STORAGE_PROPERTY_QUERY spq;
// 空间给多一点,就不用调用两次DeviceIoControl了
PSTORAGE_DEVICE_DESCRIPTOR psdd = (PSTORAGE_DEVICE_DESCRIPTOR)malloc(1024);
if (!psdd) {
CloseHandle(hDrive);
return;
}
spq.PropertyId = StorageDeviceProperty;
spq.QueryType = PropertyStandardQuery;
BOOL ret = DeviceIoControl(
hDrive, IOCTL_STORAGE_QUERY_PROPERTY,
&spq, sizeof(STORAGE_PROPERTY_QUERY),
psdd, 1024, 0, 0
);
CloseHandle(hDrive);
if (!ret) {
printf_s("[%d] DeviceIoControl: %x\n", __LINE__, GetLastError());
free(psdd);
return;
}
// Product ID, Serial Number, Vendor ID, Product Revision不一定全都存在
PSTR str;
if (psdd->ProductIdOffset) {
str = (PCHAR)psdd + psdd->ProductIdOffset;
// 虽然这些字符串都以空字符结尾,但可能以空格开头,把它们trim掉
while(*str && *str == ' ') str++;
printf_s("Product ID: %s\n", str);
}
if (psdd->SerialNumberOffset) {
str = (PCHAR)psdd + psdd->SerialNumberOffset;
while(*str && *str == ' ') str++;
printf_s("Serial Number: %s\n", str);
}
if (psdd->VendorIdOffset) {
str = (PCHAR)psdd + psdd->VendorIdOffset;
while(*str && *str == ' ') str++;
printf_s("Vendor ID: %s\n", str);
}
if (psdd->ProductRevisionOffset) {
str = (PCHAR)psdd + psdd->ProductRevisionOffset;
while(*str && *str == ' ') str++;
printf_s("Product Revision: %s\n", str);
}
free(psdd);
参考:
https://blog.csdn.net/zzy1448331580/article/details/124696129
https://blog.csdn.net/AcceZn/article/details/131075604