WMI 以不同的格式返回信息

WMI returns information in different formats

本文关键字:格式 返回 信息 WMI      更新时间:2023-10-16

我想读取硬件配置以检查我的软件许可证是否有效。目前,我尝试使用WMI.这在许多计算机上工作了数周,但有时,如果没有明显的原因,WMI以不同的格式返回硬件配置。例如,主硬盘的序列号从字符转换为十六进制字符串,所有字符十六进制值按对交换。我发现不同的Windows用户类型(管理员/普通)会影响格式,但它在其他情况下也会以不同的方式发生变化,我无法弄清楚模式。

有没有人知道如何使用 WMI 可靠地检查硬件配置?或者是否可以使用 MFC 避免上述问题?

WMI确实不可靠。当您不需要它时,您应该避免使用它。

以下是没有 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;
}

之后,您将获得一个大设备字符串。您可能希望从中读取所需的信息。
检查以下正则表达式以检索这些内容:
(请注意,字符串可以根据设备类型而更改,因此请对其进行测试并添加/调整正则表达式 - 这些来自 U 盘测试)

ven_([^&#]+)    //Vendor String/ID
prod_([^&#]+)   //Product String/ID
rev_([^&#]+)    //Revision String/ID
&[^#]*#([^&#]+) //Serial String/Number

正则表达式 ?再比如:

std::wregex(见std::basic_regex...
std::wsmatch(见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;
}

请为您的产品提供一个许可证 =)