C++中使用WMI获取用户名时出错

问题描述 投票:0回答:1

当我尝试使用 WMI 获取计算机的用户名时遇到错误:

错误:在编组或解组任何接口之前必须初始化安全性。一旦初始化就无法更改。

当我颠倒

CoInitialize()
CoInitializeSecurity()
之间的顺序时,出现此错误:

错误:CoInitialize尚未被调用。

代码如下:

HRESULT hres;
std::string userNametest;

// Initialize COM
hres = CoInitialize(NULL);
    if (FAILED(hres)) {
        _com_error err(hres);
        LPCTSTR errMsg = err.ErrorMessage();
        std::wstring w = errMsg;
        userNametest = std::string(w.begin(), w.end());
        CoUninitialize();
        if (jadedevlog.is_open()) {
            jadedevlog << "Error: " << userNametest << endl;
            jadedevlog.close();
        }
        return 1;
    }
        // Initialize security
    hres = CoInitializeSecurity(
        NULL,
        -1,
        NULL,
        NULL,
        RPC_C_AUTHN_LEVEL_DEFAULT,
        RPC_C_IMP_LEVEL_IMPERSONATE,
        NULL,
        EOAC_NONE,
        NULL);
        if (FAILED(hres)) {
            _com_error err(hres);
            LPCTSTR errMsg = err.ErrorMessage();
            std::wstring w = errMsg;
            userNametest = std::string(w.begin(), w.end());
           
            if (jadedevlog.is_open()) {
                jadedevlog << "Error: " << userNametest << endl;
                jadedevlog.close();
            }
            CoUninitialize();
            return 1;
        }
            // Obtain the initial locator to WMI
            IWbemLocator* pLoc = NULL;
            hres = CoCreateInstance(
                CLSID_WbemLocator,
                0,
                CLSCTX_INPROC_SERVER,
                IID_IWbemLocator,
                (LPVOID*)&pLoc);

            if (FAILED(hres)) {
                CoUninitialize();
                userNametest = "fail to create WbemLocator"; // Failed to create WbemLocator
                if (jadedevlog.is_open()) {
                    jadedevlog << "Error: " << userNametest << endl;
                    jadedevlog.close();
                }
                return 1;
            }
                // Connect to WMI through the IWbemLocator::ConnectServer method
                IWbemServices* pSvc = NULL;
                hres = pLoc->ConnectServer(
                    L"ROOT\\CIMv2",  // WMI namespace
                    NULL,
                    NULL,
                    0,
                    NULL,
                    0,
                    0,
                    &pSvc);

                if (FAILED(hres)) {
                    pLoc->Release();
                    CoUninitialize();
                  
                    userNametest = "Cant connect to WMI"; // Could not connect to WMI
                    if (jadedevlog.is_open()) {
                        jadedevlog << "Error: " << userNametest << endl;
                        jadedevlog.close();
                    }
                    return 1;
                }
                    // Set security levels on the proxy
                    hres = CoSetProxyBlanket(
                        pSvc,                        // 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(hres)) {
                        pSvc->Release();
                        pLoc->Release();
                        CoUninitialize();
                  
                        userNametest = "Could not set proxy blanket"; // Could not set proxy blanket
                        if (jadedevlog.is_open()) {
                            jadedevlog << "Error: " << userNametest << endl;
                            jadedevlog.close();
                        }
                        return 1;
                    }
                        // Use the IWbemServices pointer to make requests of WMI
                        IEnumWbemClassObject* pEnumerator = NULL;
                        hres = pSvc->ExecQuery(
                            L"WQL",
                            L"SELECT * FROM Win32_ComputerSystem",
                            WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY,
                            NULL,
                            &pEnumerator);

                        if (FAILED(hres)) {
                            pSvc->Release();
                            pLoc->Release();
                            CoUninitialize();
                          
                            userNametest = "fail to query for Win32_ComputerSystem"; // Query for Win32_ComputerSystem failed
                            if (jadedevlog.is_open()) {
                                jadedevlog << "Error: " << userNametest << endl;
                                jadedevlog.close();
                            }
                            return 1;
                        }
                            // Retrieve the data from the query in step 6
                            IWbemClassObject* pclsObj = NULL;
                            ULONG uReturn = 0;

                            while (pEnumerator) {
                                HRESULT hr = pEnumerator->Next(WBEM_INFINITE, 1, &pclsObj, &uReturn);

                                if (0 == uReturn) {
                                    userNametest = "no more time";
                                    break; // No more items
                                }

                                VARIANT vtProp;
                                // Get the value of the "UserName" property
                                hr = pclsObj->Get(L"UserName", 0, &vtProp, 0, 0);

                                int wslen = SysStringLen(vtProp.bstrVal);
                                int len = WideCharToMultiByte(CP_UTF8, 0, vtProp.bstrVal, wslen, nullptr, 0, nullptr, nullptr);
                                if (len <= 0)
                                    userNametest = "Convertion fail";  //convert from BSTR to string fails
                                std::string result(len, 0);
                                WideCharToMultiByte(CP_UTF8, 0, vtProp.bstrVal, wslen, &result[0], len, nullptr, nullptr);

                                VariantClear(&vtProp);
                                pclsObj->Release();
                                userNametest = result;
                            }

                            // Cleanup
                            pSvc->Release();
                            pLoc->Release();
                            pEnumerator->Release();
                            CoUninitialize(); 

发生什么事了?

c++ windows winapi wmi
1个回答
0
投票
每个线程只能调用一个

CoInitializeSecurity()
。如果它已经被调用线程调用,它将返回
RPC_E_TOO_LATE
。虽然这是一个错误条件(
FAILED()
将返回 true),但它不是一个fatal条件,但你将其视为是。在这种情况下,处理
RPC_E_TOO_LATE
时,您应该忽略
CoInitializeSecurity()

RPC_E_CHANGED_MODE
上的
CoInitialize()
相同。

© www.soinside.com 2019 - 2024. All rights reserved.