如何在C++中从Windows注册表获取计算机制造商和型号?

8

我正在编写自己的C++代码,通过读取和解析注册表键来读取Windows计算机的型号和制造商信息。

HKEY_LOCAL_MACHINE/SYSTEM/CurrentControlSet/services/mssmbios/Data/SMBiosData

在Windows/C++/Visual Studio中,是否有任何库函数可以直接获取此信息?

4
这些信息可以通过WMI(Windows Machine Instrumentation)获得,但这并不是一个简单的库函数。 - rodrigo
请勿从注册表中读取此内容。这是一项实现细节,很可能会在下一个 Windows 版本中停止工作。您已经知道了正确的操作方式,这是 Microsoft 支持的方式。为什么不采用它呢? - Stu
@Stu:与此同时,问题已经解决。你是指WMI吗?我看了一下,“但那远非一个简单的库函数”。我不需要实现在不同的Windows版本上工作:该工具只需在特定版本上工作。 - Giorgio
下面Raymond Chen提供了一个完整的、可工作的示例。你基本上是在说“我不在乎这个将来会出现问题,只要我不必跟随链接并复制粘贴可工作的代码”。这绝对让人难以置信。但是嘿,你又怎么会在意呢?当它在Windows 9上出现问题时,你可以把责任推给Windows。 - Stu
@Giorgio你有SMBIOS-Peek的链接吗?在code-project上似乎它的链接已经删除了。 - Inside Man
显示剩余5条评论
2个回答

6
您需要的步骤在使用C++创建WMI应用程序中有详细说明。MSDN甚至包括一个示例程序。您只需要更改两个字符串即可。
  1. SELECT * FROM Win32_Process更改为SELECT * FROM Win32_ComputerSystem
  2. Name更改为Manufacturer,然后再次更改Model

我甚至不知道你在这个网站上,雷蒙德。让我爬一会儿吧——好了,现在好多了。 - Stu

5
借助 微软示例代码 的帮助,我成功创建了这个方法。
#include <Wbemidl.h>
#pragma comment(lib, "wbemuuid.lib")

std::pair<CString,CString> getComputerManufacturerAndModel() {
    // Obtain the initial locator to Windows Management on a particular host computer.
    IWbemLocator *locator = nullptr;
    IWbemServices *services = nullptr;
    auto hResult = CoCreateInstance(CLSID_WbemLocator, 0, CLSCTX_INPROC_SERVER, IID_IWbemLocator, (LPVOID *)&locator);

    auto hasFailed = [&hResult]() {
        if (FAILED(hResult)) {
            auto error = _com_error(hResult);
            TRACE(error.ErrorMessage());
            TRACE(error.Description().Detach());
            return true;
        }
        return false;
    };

    auto getValue = [&hResult, &hasFailed](IWbemClassObject *classObject, LPCWSTR property) {
        CString propertyValueText = "Not set";
        VARIANT propertyValue;
        hResult = classObject->Get(property, 0, &propertyValue, 0, 0);
        if (!hasFailed()) {
            if ((propertyValue.vt == VT_NULL) || (propertyValue.vt == VT_EMPTY)) {
            } else if (propertyValue.vt & VT_ARRAY) {
                propertyValueText = "Unknown"; //Array types not supported
            } else {
                propertyValueText = propertyValue.bstrVal;
            }
        }
        VariantClear(&propertyValue);
        return propertyValueText;
    };

    CString manufacturer = "Not set";
    CString model = "Not set";
    if (!hasFailed()) {
        // Connect to the root\cimv2 namespace with the current user and obtain pointer pSvc to make IWbemServices calls.
        hResult = locator->ConnectServer(L"ROOT\\CIMV2", nullptr, nullptr, 0, NULL, 0, 0, &services);

        if (!hasFailed()) {
            // Set the IWbemServices proxy so that impersonation of the user (client) occurs.
            hResult = CoSetProxyBlanket(services, RPC_C_AUTHN_WINNT, RPC_C_AUTHZ_NONE, nullptr, RPC_C_AUTHN_LEVEL_CALL,
                RPC_C_IMP_LEVEL_IMPERSONATE, nullptr, EOAC_NONE);

            if (!hasFailed()) {
                IEnumWbemClassObject* classObjectEnumerator = nullptr;
                hResult = services->ExecQuery(L"WQL", L"SELECT * FROM Win32_ComputerSystem", WBEM_FLAG_FORWARD_ONLY |
                    WBEM_FLAG_RETURN_IMMEDIATELY, nullptr, &classObjectEnumerator);
                if (!hasFailed()) {
                    IWbemClassObject *classObject;
                    ULONG uReturn = 0;
                    hResult = classObjectEnumerator->Next(WBEM_INFINITE, 1, &classObject, &uReturn);
                    if (uReturn != 0) {
                        manufacturer = getValue(classObject, (LPCWSTR)L"Manufacturer");
                        model = getValue(classObject, (LPCWSTR)L"Model");
                    }
                    classObject->Release();
                }
                classObjectEnumerator->Release();
            }
        }
    }

    if (locator) {
        locator->Release();
    }
    if (services) {
        services->Release();
    }
    CoUninitialize();
    return { manufacturer, model };
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接