Получение кода ID процессора из C# в C++

У меня есть этот код C# для получения идентификатора процессора, но я не могу передать его в C++, я много пробовал, но я действительно не могу, я только начал в C++, и я хотел бы иметь возможность получить идентификатор процессора с C++, как я привык получать с C#

Это код, который я имею в C#:

public static string GetProcessorID()
{
  string sProcessorID = "";
  string sQuery = "SELECT ProcessorId FROM Win32_Processor";
  ManagementObjectSearcher oManagementObjectSearcher = new ManagementObjectSearcher(sQuery);
  ManagementObjectCollection oCollection = oManagementObjectSearcher.Get();
  foreach (ManagementObject oManagementObject in oCollection)
  {
    sProcessorID = (string)oManagementObject["ProcessorId"];
  }

  return (sProcessorID);
}

2 ответа

Решение

Это немного дольше в C++! Это полный рабочий пример, обратите внимание, что если вы измените запрос с

SELECT ProcessorId FROM Win32_Processor

в

SELECT * FROM Win32_Processor

Тогда вы можете использовать QueryValue функция для запроса любого значения свойства.

HRESULT GetCpuId(char* cpuId, int bufferLength)
{
    HRESULT result = InitializeCom();
    if (FAILED(result))
        return result;

    IWbemLocator* pLocator = NULL;
    IWbemServices* pService = NULL;
    result = GetWbemService(&pLocator, &pService);
    if (FAILED(result))
    {
        CoUninitialize();
        return result;
    }

    memset(cpuId, 0, bufferLength);
    result = QueryValue(pService, 
            L"SELECT ProcessorId FROM Win32_Processor", L"ProcessorId",
            cpuId, bufferLength);

    if (FAILED(result))
    {
        pService->Release();
        pLocator->Release();
        CoUninitialize();

        return result;
    }

    pService->Release();
    pLocator->Release();
    CoUninitialize();

    return NOERROR;
}

Сначала вы должны выполнить все вещи инициализации, они упакованы в эти две функции:

HRESULT InitializeCom()
{
    HRESULT result = CoInitializeEx(0, COINIT_APARTMENTTHREADED); 
    if (FAILED(result))
        return result;

    result = CoInitializeSecurity(
        NULL,                           // pSecDesc
        -1,                             // cAuthSvc (COM authentication)
        NULL,                           // asAuthSvc
        NULL,                           // pReserved1
        RPC_C_AUTHN_LEVEL_DEFAULT,      // dwAuthnLevel
        RPC_C_IMP_LEVEL_IMPERSONATE,    // dwImpLevel
        NULL,                           // pAuthList
        EOAC_NONE,                      // dwCapabilities
        NULL                            // Reserved
        );

    if (FAILED(result) && result != RPC_E_TOO_LATE)
    {
        CoUninitialize();

        return result;
    }

    return NOERROR;
}

HRESULT GetWbemService(IWbemLocator** pLocator, IWbemServices** pService)
{
    HRESULT result = CoCreateInstance(CLSID_WbemLocator, 0, CLSCTX_INPROC_SERVER, 
        IID_IWbemLocator, reinterpret_cast<LPVOID*>(pLocator));

    if (FAILED(result))
    {
        return result;
    }

    result = (*pLocator)->ConnectServer(
        _bstr_t(L"ROOT\\CIMV2"),    // strNetworkResource
        NULL,                       // strUser  
        NULL,                       // strPassword
        NULL,                       // strLocale
        0,                          // lSecurityFlags
        NULL,                       // strAuthority
        NULL,                       // pCtx
        pService                    // ppNamespace
        );

    if (FAILED(result))
    {
        (*pLocator)->Release();     

        return result;
    }

    result = CoSetProxyBlanket(
        *pService,                      // pProxy
        RPC_C_AUTHN_WINNT,              // dwAuthnSvc
        RPC_C_AUTHZ_NONE,               // dwAuthzSvc
        NULL,                           // pServerPrincName
        RPC_C_AUTHN_LEVEL_CALL,         // dwAuthnLevel
        RPC_C_IMP_LEVEL_IMPERSONATE,    // dwImpLevel
        NULL,                           // pAuthInfo
        EOAC_NONE                       // dwCapabilities
        );

    if (FAILED(result))
    {
        (*pService)->Release();
        (*pLocator)->Release();     

        return result;
    }

    return NOERROR;
}

После этого вы можете выполнить свой WQL-запрос, затем вам нужно перечислить возвращаемые свойства, чтобы найти то, что вам нужно (вы можете упростить его, но таким образом вы можете запросить несколько значений). Обратите внимание, что если вы запросите ВСЕ значения из Win32_Processor, вы получите много данных. В некоторых системах я видел, что для выполнения запроса и перечисления свойств требуется даже 2 секунды (поэтому отфильтруйте запрос так, чтобы он включал только те данные, которые вам нужны).

HRESULT QueryValue(IWbemServices* pService, const wchar_t* query, const wchar_t* propertyName, char* propertyValue, int maximumPropertyValueLength)
{
    USES_CONVERSION;

    IEnumWbemClassObject* pEnumerator = NULL;
    HRESULT result = pService->ExecQuery(
        bstr_t(L"WQL"),                                         // strQueryLanguage
        bstr_t(query),                                          // strQuery
        WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY,  // lFlags
        NULL,                                                   // pCtx
        &pEnumerator                                            // ppEnum
        );

    if (FAILED(result))
        return result;

    IWbemClassObject *pQueryObject = NULL;
    while (pEnumerator)
    {
        try
        {
            ULONG returnedObjectCount = 0;
            result = pEnumerator->Next(WBEM_INFINITE, 1, &pQueryObject, &returnedObjectCount);

            if (returnedObjectCount == 0)
                break;

            VARIANT objectProperty;
            result = pQueryObject->Get(propertyName, 0, &objectProperty, 0, 0);
            if (FAILED(result))
            {
                if (pEnumerator != NULL)
                    pEnumerator->Release();

                if (pQueryObject != NULL)
                    pQueryObject->Release();

                return result;
            }

            if ((objectProperty.vt & VT_BSTR) == VT_BSTR)
            {
                strcpy_s(propertyValue, maximumPropertyValueLength, OLE2A(objectProperty.bstrVal));
                break;
            }

            VariantClear(&objectProperty);
        }
        catch (...)
        {
            if (pEnumerator != NULL)
                pEnumerator->Release();

            if (pQueryObject != NULL)
                pQueryObject->Release();

            return NOERROR;
        }
    } 

    if (pEnumerator != NULL)
        pEnumerator->Release();

    if (pQueryObject != NULL)
        pQueryObject->Release();

    return NOERROR;
}

ПРИМЕЧАНИЕ: этот код полезен, если вам нужно собрать больше информации, чем простой идентификатор процессора. Это общий пример получения одного (или нескольких) свойств из запроса WQL (как вы это делали в C#). Если вам не нужно получать какую-либо другую информацию (и вы не планируете использовать WMI в своих программах на C++), вы можете использовать __cpuid() встроенный, как опубликовано в комментарии.

__cpuid ()

ProcessorId свойство от WMI имеет следующее описание:

Информация о процессоре, которая описывает функции процессора. Для CPU класса x86 формат поля зависит от поддержки процессором инструкции CPUID. Если инструкция поддерживается, свойство содержит 2 (два) значения в формате DWORD. Первым является смещение 08h-0Bh, которое является значением EAX, которое инструкция CPUID возвращает с входом EAX, установленным на 1. Второе, является смещением 0Ch-0Fh, которое является значением EDX, которое возвращает инструкция. Только первые два байта свойства являются значимыми и содержат содержимое регистра DX при перезагрузке ЦП - все остальные установлены в 0 (ноль), а содержимое в формате DWORD.

Хорошая реализация должна проверять больше о странных случаях, но наивная реализация может быть:

std::string GetProcessorId()
{
 int info[4] = { -1 };

 __cpuid(info, 0);
 if (info[0] < 1)
  return ""; // Not supported?!

 // Up to you...you do not need to mask results and you may use
 // features bits "as is".    
 __cpuid(info, 1);
 int family = info[0];
 int features = info[3];

 std::stringstream id;
 id << std::hex << std::setw(4) << std::setfill('0') << family << features;

 return id.str();
}

Смотрите также этот пост для лучшей реализации C++.

  1. Если проблема заключается только в отправке полученного ProcessorID типа string (управляемого кода) в неуправляемый код (C++), то вы можете попробовать различные варианты, такие как использование интерфейса COM или некоторого промежуточного интерфейса CLR CLR или использование обычной нативной записи DLL сортировать код по своему усмотрению.

  2. Другой способ - создать интерфейс C# COM и получить к нему доступ из C++, чтобы получить sProcessorID, вызвав вашу функцию GetProcessorID().

Другие вопросы по тегам