4

プロセッサ ID を取得するためのこの C# コードがありますが、C++ に渡すことができません。いろいろ試しましたが、実際にはできません。C++ で始めたばかりで、CPU ID を取得できるようにしたいと考えています。 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);
}
4

2 に答える 2

6

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

まず、すべての初期化を行う必要があります。これらは次の2つの関数にパックされています。

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

注:このコードは、CPUの単純なIDよりも多くの情報を収集する必要がある場合に役立ちます。これは、(C#で行ったように)WQLクエリから1つ(または複数)のプロパティを取得する一般的な例です。他の情報を取得する必要がない場合(およびC ++プログラムでWMIを使用することを考えていない場合)__cpuid()、コメントに投稿されている組み込み関数を使用できます。

__cpuid()

WMIのProcessorIdプロパティには次の説明があります。

プロセッサー機能を説明するプロセッサー情報。x86クラスCPUの場合、フィールド形式はCPUID命令のプロセッササポートによって異なります。命令がサポートされている場合、プロパティには2つのDWORD形式の値が含まれます。1つ目は08h-0Bhのオフセットで、CPUID命令が入力EAXを1に設定して返すEAX値です。2つ目は0Ch-0Fhのオフセットで、命令が返すEDX値です。プロパティの最初の2バイトのみが重要であり、CPUリセット時の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++風の実装については、この投稿も参照してください。

于 2012-04-19T13:58:45.000 に答える
0
  1. 取得した文字列型 (マネージ コード) の ProcessorID をアンマネージ コード (C++) に送信するだけの問題である場合は、COM インターフェイスを使用するか、中間の CLR CLI インターフェイスを使用するか、通常のネイティブ dll 書き込みを使用するなど、さまざまなオプションを試すことができます。自分でコードをマーシャリングします。

  2. もう 1 つの方法は、C# COM インターフェイスを作成し、C++ からアクセスして、関数 GetProcessorID() を呼び出して sProcessorID を取得することです。

于 2012-04-19T14:07:43.767 に答える