返回

解决 C++ WMI 枚举和获取实例方法失败的问题

windows

解决 C++ WMI 枚举和获取实例方法失败的问题

简介

在尝试使用 C++ WMI 查找和设置新创建的 VHD 磁盘时,您可能遇到错误 HRESULT 0x8004101e,这表明您使用了错误的根目录或其他问题。本文将深入探讨这个问题,提供循序渐进的解决方法,并提供一个经过修复的代码示例。

问题根源

WMI 故障可能有多种原因,包括:

  • 使用了错误的根目录或其他命名空间
  • 无法获取方法接口
  • 方法名或参数签名不正确
  • 权限不足
  • 防火墙设置阻碍连接

解决方法

解决此问题需要以下步骤:

1. 验证 WMI 连接

  • 确保使用正确的根目录路径:ROOT\\cimv2\\storage

2. 检查方法可用性

  • 尝试使用 GetMethod 方法获取方法接口,如果失败,表明方法不可用。

3. 确定正确的方法名

  • 对于 Format 方法,使用以下名称:_bstr_t methodName(L"Format");

4. 检查参数签名

  • 确保方法调用的参数签名与所需的参数匹配。

5. 确保权限

  • 以具有适当权限(如管理员权限)的帐户运行代码。

6. 检查防火墙设置

  • 确保防火墙未阻止 WMI 连接。

修复后的代码示例

以下是修改后的代码示例:

int main() {
    int ret = -2;
    try {
        CComPtr<IWbemLocator> wbemLocator;
        CComPtr<IWbemServices> wbemServices;
        HRESULT hr = CoInitializeEx(0, COINIT_MULTITHREADED);
        if (FAILED(hr))
            throw std::runtime_error("Failed to initialize COM");
        // flag COM as initialized
        ret = -1;
        // Set general COM security levels --------------------------
        hr = CoInitializeSecurity(NULL,
            -1,                          // COM authentication
            NULL,                        // Authentication services
            NULL,                        // Reserved
            RPC_C_AUTHN_LEVEL_DEFAULT,   // Default authentication 
            RPC_C_IMP_LEVEL_IMPERSONATE, // Default Impersonation  
            NULL,                        // Authentication info
            EOAC_NONE,                   // Additional capabilities 
            NULL);                         // Reserved
        if (FAILED(hr))
            throw std::runtime_error("Failed to initialize security");
        // Obtain the initial locator to WMI -------------------------
        hr = CoCreateInstance(CLSID_WbemLocator, 0, CLSCTX_INPROC_SERVER, IID_IWbemLocator, (LPVOID*)&wbemLocator);
        if (FAILED(hr))
            throw std::runtime_error("Failed to create IWbemLocator");
        // Connect to the ROOT\\\microsoft\\windows\\storage
        hr = wbemLocator->ConnectServer(
            _bstr_t(L"ROOT\\cimv2\\storage"), // Object path of WMI namespace
            NULL,                    // User name. NULL = current user
            NULL,                    // User password. NULL = current
            0,                       // Locale. NULL indicates current
            NULL,                    // Security flags.
            0,                       // Authority (for example, Kerberos)
            0,                       // Context object 
            &wbemServices);         // pointer to IWbemServices proxy
        if (FAILED(hr))
            throw std::runtime_error("Could not connecct");
        // Set security levels on the proxy -------------------------
        hr = CoSetProxyBlanket(
            wbemServices,                        // Indicates the proxy to set
            RPC_C_AUTHN_WINNT,           // RPC_C_AUTHN_xxx
            RPC_C_AUTHZ_NONE,            // RPC_C_AUTHZ_xxx
            NULL,                        // Server principal name 
            RPC_C_AUTHN_LEVEL_CALL,      // RPC_C_AUTHN_LEVEL_xxx 
            RPC_C_IMP_LEVEL_IMPERSONATE, // RPC_C_IMP_LEVEL_xxx
            NULL,                        // client identity
            EOAC_NONE);                  // proxy capabilities 
        if (FAILED(hr))
            throw std::runtime_error("CoSetProxyBlanket()");
        // do the work
        EnumVolume(wbemServices);
        ret = 0;
    }
    catch (const std::exception& ex) {
        std::cout << "Exception: " << ex.what() << std::endl;
    }
    // is it safe>?
    if (ret >= -1)
        CoUninitialize();
    return ret;
}

结论

通过遵循本文中的步骤,您可以解决 C++ WMI 枚举和获取实例方法失败的问题。请注意,代码仅作为示例,应根据具体情况进行调整。

常见问题解答

1. 为什么我会收到错误 HRESULT 0x8004101e?

  • 此错误可能是由于以下原因之一造成的:使用了错误的根目录、无法获取方法接口、方法名或参数签名不正确、权限不足或防火墙设置阻止连接。

2. 如何验证 WMI 连接?

  • 在连接到 WMI 时,使用正确的根目录路径:ROOT\\cimv2\\storage

3. 如何检查方法可用性?

  • 尝试使用 GetMethod 方法获取方法接口,如果失败,表明方法不可用。

4. 如何确保权限?

  • 以具有适当权限(如管理员权限)的帐户运行代码。

5. 如何检查防火墙设置?

  • 确保防火墙未阻止 WMI 连接。