Получение кода идентификатора ЦП из С# в С++

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

Это код, который у меня есть на С#:

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);
}

person Luiza Nunes    schedule 19.04.2012    source источник
comment
Пожалуйста, посмотрите на это: stackoverflow.com/questions/5658975/c-get-processor-id   -  person Lucian    schedule 19.04.2012
comment
Я прочитал это, согласно этому сообщению, мне нужно было бы перейти по адресу: msdn.microsoft.com/en-us/library/hskdteyh%28v=vs.80%29.aspx, и я это сделал, но там много информации, в которой я не уверен что я хочу. Вывод представляет собой шестнадцатеричные значения для различных типов ЦП. Я этого не понимаю.   -  person Luiza Nunes    schedule 19.04.2012


Ответы (2)


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

SELECT ProcessorId FROM Win32_Processor

to

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;
}

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

__процессор()

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

Информация о процессоре, описывающая функции процессора. Для ЦП класса 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++.

person Adriano Repetti    schedule 19.04.2012
comment
хм, большое спасибо, Адриано, не могли бы вы опубликовать небольшой пример получения идентификатора с помощью __cpuid()? потому что мне нужно, чтобы уникальный номер идентификации процессора был std::string, чтобы я мог хранить его в базе данных. Спасибо! - person Luiza Nunes; 19.04.2012
comment
Функция GetProcessorId возвращает значение, отличное от Win32_Processor? - person user1633272; 28.10.2018
comment
@user да, немного отличается, но вы можете настроить маску (и проверить обновленные документы!), Чтобы иметь то же значение - person Adriano Repetti; 28.10.2018
comment
Это совсем другое: ProcessId=BFEBFBFF000306A9, а GetProcessorId() возвращает 0600f000. - person user1633272; 28.10.2018
comment
Измените или удалите маску, но я понятия не имею, откуда берутся лишние байты (надо действительно сравнить, что сейчас возвращает амур) - person Adriano Repetti; 28.10.2018

  1. Если это просто проблема отправки полученного ProcessorID строки типа (управляемый код) в неуправляемый код (С++), то вы можете попробовать различные варианты, такие как использование COM-интерфейса или через какой-либо промежуточный интерфейс CLR CLI или с помощью обычной записи собственной dll маршалинговый код самостоятельно.

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

person VPK    schedule 19.04.2012