无需 WMI 即可获取物理硬盘序列号






4.79/5 (56投票s)
使用 DeviceIOControl 等低级 API 检索物理硬盘 ID 和其他信息。
引言
许多需要保护其作品的人需要获取一些硬件特定的信息,例如 MAC 地址或某些硬盘的序列号。
背景
如果您尝试过其他解决方案,例如像这个,它可能对您不起作用,因为它使用了 WMI 服务。 我找到了一种效果不错的解决方案在这里。 它使用 DeviceIoControl
API 发送的命令对磁盘进行低级调用。 除非您使用原生 C++,否则该代码不太可重用。 因此,我对其进行了一些修改,使其看起来更面向对象。 最重要的是,我通过 .NET 集合公开了驱动器信息。
Using the Code
由于该集合是用 MC++ 编写的,因此我在演示 zip 文件中包含了一些可再发行包中的 Microsoft DLL。 此外,必须使用 .NET 2.0,因为该集合是泛型的。
该代码非常易于从任何 .NET 语言使用,例如 C#。
m_list = new DriveListEx();
m_list.Load();
//bind to a a grid view
m_dataGridView.DataSource = m_list;
关注点
内部驱动器信息在 DiskInfo::LoadDiskInfo();
中收集。
DiskInfo
是一个原生单例类,它封装了对 ReadPhysicalDriveInNTWithAdminRights()
和 ReadIdeDriveAsScsiDriveInNT()
的调用。 我忽略了 ReadPhysicalDriveInNTWithZeroRights()
,因为它似乎根本不起作用。
如果它们可以检索到信息,这两个函数将调用 AddIfNew()
。
内部有一个列表,其中保存了有关驱动器的原始信息,并且在找到新的驱动器信息时会更新该列表。
BOOL DiskInfo::AddIfNew(USHORT *pIdSector)
{
BOOL bAdd = TRUE;
for(UINT i =0; i< m_list.size();i++)
{
if(memcmp(pIdSector,m_list[i],256 * sizeof(WORD)) == 0)
{
bAdd = false;
break;
}
}
if(bAdd)
{
WORD* diskdata = new WORD[256];
::memcpy(diskdata,pIdSector,256*sizeof(WORD));
m_list.push_back(diskdata);
}
return bAdd;
}
如果您使用非 .NET 编译器,仍然可以使用 UnmanagedCode.cpp 中的源代码,只需取消注释 #define NATIVE_CODE
行即可。
此构建适用于 Windows XP 32 位系统。 如果您需要它用于 Vista 或 64 位系统,则应在构建时选择正确的 include 和 lib 文件夹,并且不应使用 release.zip 存档中的其他 DLL,因为它们是 Windows XP 的 32 位。
历史
- 版本 1.1:添加了
ReadPhysicalDriveInNTUsingSmart
以读取 HDD 信息。
顺便说一句,我还没有机会在 Windows 95 及类似系统上进行测试。