查询硬盘序号总结

问题描述

刚开始获取硬件信息的时候找了很多方法,但最终效果并不是特别好,直到现在找到了可靠的方法,现在总结下来,希望你能在这里得到一些思路。

查询硬盘序号的方法

正确的序列号,使用软件CrystalDiskInfo或者AIDA64可以查询到。
CrystalDiskInfo
AIDA64

一、WMI

这两种方式应该没有太大区分

  • WMI命令行
wmic diskdrive get serialnumber

效果:
wmic

  • WQL工具
    WQL

二、DeviceIoControl

参考链接,以下是部分代码,不完全。

/************************************************************************
GetHDSerial:用于获取指定编号的硬盘序列号,无需任何权限提升
参数:
PCHAR pszIDBuff:传入的字符串缓冲区,用于接收硬盘序列号
int nBuffLen:传入的字符串缓冲区大小,当硬盘序列号大于该值时,只复制nBuffLen长度
int nDriveID:要获取的驱动器编号,从0开始,到15为止
返回值:
成功获取到的硬盘序列号长度,为0表示获取失败
作者:
famous214(blog.csdn.net/LPWSTR)
源码参考了diskid32(https://www.winsim.com/diskid32/diskid32.html)
版本历史:
20171226 第一版,从diskid32源码中提取
20171226 第二版,兼容Unicode编译方式
20171230 重构后发布第三版
************************************************************************/
ULONG GetHDSerial(PCHAR pszIDBuff, int nBuffLen, int nDriveID)
{
    HANDLE hPhysicalDrive = INVALID_HANDLE_VALUE;
    ULONG ulSerialLen = 0;
    __try
    {
        //  Try to get a handle to PhysicalDrive IOCTL, report failure
        //  and exit if can't.
        TCHAR szDriveName[32];
        wsprintf(szDriveName, TEXT("\\\\.\\PhysicalDrive%d"), nDriveID);

        //  Windows NT, Windows 2000, Windows XP - admin rights not required
        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)
        {
            std::cout << nDriveNum + 1 << "," << szBuff << endl;
            // _tprintf(TEXT("第%d块硬盘的序列号为:%hs\n"), nDriveNum + 1, szBuff);
        }

    }
}

效果:
win32

三、Smartmontools

这个工具是监控硬盘用的,里面包含了硬件信息我顺便拿过来测试了下,开源有代码,以命令行的形式还是可能用在程序里面的,主页
SmartCtrl

四、CrystalDiskInfo

没想到这个软件也是可以下到源代码的,主页

查看了内部实现的代码,本质上也就是DeviceIoControl+WQL的方式再把硬盘的序列号提取再拼凑起来的,这时才明白过来看似简单的得到硬盘序号并没有想象的那么简单。

相关代码已上传,
下载地址:https://www.123pan.com/s/R0XNjv-QwxGd.html提取码:6666

DiskInfoExtend

最后

感谢各位大佬的无私奉献。

Logo

瓜分20万奖金 获得内推名额 丰厚实物奖励 易参与易上手

更多推荐