WMI返回不同格式的信息 [英] WMI returns information in different formats
问题描述
我想阅读硬件配置,以检查我的软件许可证是否有效.目前,我尝试使用WMI
.这在许多机器上都可以正常工作数周,但有时,WMI
会在没有明显原因的情况下以另一种格式返回硬件配置.例如,主硬盘的序列号从字符转换为十六进制字符串,所有字符十六进制值都成对交换.我发现不同的Windows用户类型(管理员/普通用户)会影响格式,但在其他情况下以及以不同的方式也会发生变化,因此我无法找出一种模式.
I want to read the hardware configuration to check if a license for my software is valid. Currently, I tried using WMI
. This works fine on many machines for several weeks but sometimes, without an obvious reason, WMI
returns the hardware configuration in a different format. For example, the serial number of the primary hard disc is converted from characters to a hex string, with all character hex values being swapped pair wise. I figured out that different Windows user types (admin/normal) influence the format but it also changes in other situations and in different ways, for which I am unable to figure out a pattern.
有人知道如何使用WMI
可靠地检查硬件配置吗?还是可以使用MFC
来避免上述问题?
Does anybody know how to reliably check the hardware configuration using WMI
? Or would it be possible to avoid the above problem using MFC
?
推荐答案
WMI确实不可靠.不需要时应避免使用它.
WMI is indeed unreliable. You should avoid using it when you don't need it.
这是没有WMI的一种方法:
Here's one way without WMI:
#include <string>
#include <Dbt.h>
#include <winioctl.h>
#include <SetupAPI.h>
#pragma comment(lib, "SetupAPI.lib")
#include <initguid.h>
DWORD getDeviceNumber(HANDLE hDeviceHandle)
{
STORAGE_DEVICE_NUMBER sdn = { 0 };
sdn.DeviceNumber = -1;
DWORD dwBytesReturned = 0;
if (!DeviceIoControl(hDeviceHandle, IOCTL_STORAGE_GET_DEVICE_NUMBER, nullptr, 0, &sdn, sizeof(sdn), &dwBytesReturned, nullptr))
{
return -1; //Error
}
return sdn.DeviceNumber;
}
bool GetDeviceString(std::wstring &out)
{
wchar_t wDevicePath[] = L"\\\\.\\@:";
wDevicePath[4] = L'C'; //Replace this with your drive-letter & adjust code (C: / D: whatever)
HANDLE deviceHandle = CreateFileW(wDevicePath, 0, FILE_SHARE_READ | FILE_SHARE_WRITE, nullptr, OPEN_EXISTING, 0, nullptr);
if (deviceHandle == INVALID_HANDLE_VALUE)
return false;
DWORD dwVolumeDeviceNumber = getDeviceNumber(deviceHandle);
CloseHandle(deviceHandle);
HDEVINFO hDevInfo = SetupDiGetClassDevsW(&GUID_DEVINTERFACE_DISK, nullptr, nullptr, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);
if (hDevInfo == INVALID_HANDLE_VALUE)
return false; //Error
std::vector<BYTE> buf(1024);
PSP_DEVICE_INTERFACE_DETAIL_DATA_W psp = reinterpret_cast<PSP_DEVICE_INTERFACE_DETAIL_DATA_W>(buf.data());
SP_DEVICE_INTERFACE_DATA spInt;
SP_DEVINFO_DATA spDev;
spInt.cbSize = sizeof(spInt);
DWORD dwIndex = 0;
while (true)
{
if (!SetupDiEnumDeviceInterfaces(hDevInfo, nullptr, &GUID_DEVINTERFACE_DISK, dwIndex, &spInt))
break;
DWORD dwSize = 0;
SetupDiGetDeviceInterfaceDetailW(hDevInfo, &spInt, nullptr, 0, &dwSize, nullptr);
if (dwSize && dwSize <= buf.size())
{
psp->cbSize = sizeof(*psp);
memset(&spDev, sizeof(spDev), 0);
spDev.cbSize = sizeof(spDev);
long res = SetupDiGetDeviceInterfaceDetailW(hDevInfo, &spInt, psp, dwSize, &dwSize, &spDev);
if (res)
{
HANDLE hDrive = CreateFileW(psp->DevicePath, 0, FILE_SHARE_READ | FILE_SHARE_WRITE, nullptr, OPEN_EXISTING, 0, nullptr);
if (hDrive != INVALID_HANDLE_VALUE)
{
DWORD dwUsbDeviceNumber = getDeviceNumber(hDrive);
if (dwUsbDeviceNumber == dwVolumeDeviceNumber)
{
//Found
out = psp->DevicePath;
break;
}
}
CloseHandle(hDrive);
}
}
++dwIndex;
}
SetupDiDestroyDeviceInfoList(hDevInfo);
if (out.empty()) //Was not found
return false;
return true;
}
在那之后,您将获得一个大的设备字符串.您可能想从中读取所需的信息.
检查以下正则表达式以检索它们:
(请注意,字符串可能会更改,具体取决于设备类型,因此请对其进行测试并添加/调整正则表达式-这些均来自USB棒测试)
After that, you will get a large device string. You might want to read the needed information out of it.
Check the following regular expressions to retrieve these:
(Note that the string CAN change, depending on the device-type, so test it and add/adjust the regular expressions - these are from an USB-stick test)
ven_([^&#]+) //Vendor String/ID
prod_([^&#]+) //Product String/ID
rev_([^&#]+) //Revision String/ID
&[^#]*#([^&#]+) //Serial String/Number
正则表达式?另一个例子:
Regular expressions ? Another example:
std::wregex
(请参见 std::wsmatch
(请参阅
std::wregex
(see std::basic_regex
...).
std::wsmatch
(see std::match_results
...)
std::wstring wsDeviceString;
if (GetDeviceString(wsDeviceString))
{
std::wregex regexSerialNumber(L"&[^#]*#([^&#]+)");
std::wsmatch match;
if (std::regex_search(wsDeviceString, match, regexSerialNumber))
std::wcout << L"Serial Number of device is: " << match[1].str() << std::endl;
}
请给您的产品一个许可证=)
One license for your product please =)
这篇关于WMI返回不同格式的信息的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!