在保护工作成果时,获取硬件特定的信息,如MAC地址或硬盘序列号,是至关重要的。如果尝试过其他解决方案,如WMI服务,可能因为兼容性问题而无法正常工作。本文将介绍一种通过调用DeviceIoControl API来获取硬盘信息的方法,这种方法在.NET环境中使用起来非常便捷。
在尝试获取硬盘信息时,通常会使用一些底层的调用,例如DeviceIoControl API。这种方法虽然有效,但代码的复用性较差,除非使用原生C++。为了提高代码的可读性和复用性,对其进行了改进,使其更加面向对象,并在.NET集合中公开了硬盘信息。
由于集合是用MC++编写的,在演示压缩包中包含了一些来自可再发行包的Microsoft DLL。此外,必须使用.NET 2.0,因为集合是泛型的。
下面的C#代码示例展示了如何使用这个集合:
C# m_list = new DriveListEx();
m_list.Load();
// 绑定到一个GridView
m_dataGridView.DataSource = m_list;
这段代码非常简单,可以轻松地从任何.NET语言中使用,例如C#。
内部驱动器的信息是在DiskInfo::LoadDiskInfo()中收集的。DiskInfo是一个原生的单例类,它封装了对ReadPhysicalDriveInNTWithAdminRights()和ReadIdeDriveAsScsiDriveInNT()的调用。忽略了ReadPhysicalDriveInNTWithZeroRights(),因为它似乎不起作用。
这两个函数在能够检索到信息时会调用AddIfNew()。内部有一个列表,用于保存驱动器的原始信息,并在发现新的驱动器信息时更新。
如果使用的是非.NET编译器,仍然可以使用UnmanagedCode.cpp中的源代码,只需取消注释#define NATIVE_CODE行即可。这个构建是为Windows XP 32位系统准备的。如果需要在Vista或64位系统上使用,应该在构建时选择正确的include和lib文件夹,并且不应该使用release.zip存档中的额外DLL,因为它们是为Windows XP 32位系统准备的。
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;
}
版本1.1:增加了ReadPhysicalDriveInNTUsingSmart,用于读取硬盘信息。