获取CPU ID代码,从C#是在C ++ [英] Getting CPU ID code from C# to be in C++

查看:286
本文介绍了获取CPU ID代码,从C#是在C ++的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有这个C#代码获取处理器ID,但我不能将它传递给C ++,我尝试了很多,但我真的不能,我刚刚开始在C + +,我想要能够得到CPU ID和C ++一样,像C#一样

I have this C# code to get Processor ID but I'm not able to pass it to C++, I tried a lot but I really can't, I just started in C++ and I would like to be able to get the CPU ID with C++ like I used to get with 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);
}


推荐答案

C ++!这是一个完整的工作示例,请注意,如果您更改来自

It's a little bit longer in C++! This is a full working example, note that if you change the query from

SELECT ProcessorId FROM Win32_Processor

SELECT * FROM Win32_Processor

然后您可以使用 QueryValue 函数查询任何属性值。

Then you can use the QueryValue function to query any property value.

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



首先你必须做所有的初始化工作,两个函数:

First you have to do all the initialization stuffs, they're packed into these two functions:

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秒​​钟(因此过滤查询只包含所需的数据)。

That done you can run your WQL query then you have to enumerate returned properties to find the one you need (you can make it simpler but in this way you can query multiple values). Note that if you query ALL values from Win32_Processor you'll get a lot of data. On some systems I saw it takes even 2 seconds to complete the query and to enumerate properties (so filter your query to include only data you need).

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更多的信息。这是一个通用示例,从WQL查询中获取一个(或多个)属性(如在C#中做的那样)。如果你不需要得到任何其他信息(并且你不认为在你的C ++程序中使用WMI),那么你可以使用 __ cpuid()

NOTE: this code is useful if you need to gather more informations than the simple ID of the CPU. It's a generic example to get one (or more) properties from a WQL query (as you did in C#). If you do not need to get any other information (and you do not think to use WMI in your C++ programs) then you may use the __cpuid() intrinsic as posted in a comment.

ProcessorId 属性来自WMI具有以下描述:

The ProcessorId property from WMI has following description:


描述处理器功能的处理器信息。对于
x86类CPU,字段格式取决于处理器对
CPUID指令的支持。如果支持指令,则属性
包含2(二)个DWORD格式的值。第一个是
08h-0Bh的偏移量,它是CPUID指令返回的EAX值,
输入EAX设置为1.第二个是0Ch-0Fh的偏移量,它是
指令返回的EDX值。只有
的前两个字节的属性是有效的,并且包含在CPU复位时DX
寄存器的内容 - 所有其他都设置为0(零),内容
在DWORD格式。

Processor information that describes the processor features. For an x86 class CPU, the field format depends on the processor support of the CPUID instruction. If the instruction is supported, the property contains 2 (two) DWORD formatted values. The first is an offset of 08h-0Bh, which is the EAX value that a CPUID instruction returns with input EAX set to 1. The second is an offset of 0Ch-0Fh, which is the EDX value that the instruction returns. Only the first two bytes of the property are significant and contain the contents of the DX register at CPU reset—all others are set to 0 (zero), and the contents are in DWORD format.

一个好的实现应该检查更多关于奇怪的情况,但是一个幼稚的实现可能是:

A good implementation should check more about strange cases but a naive implementation may be:

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] & 0xf00;
 int features = info[3] & 0xf000;

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

 return id.str();
}

这篇关于获取CPU ID代码,从C#是在C ++的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆