VC6调用WMI编程——平台搭建

wmi example

微软MSDN的一个例子在vc6下编译测试通过

#include  //用到了CString 的 BSTR转ANSI
#define _WIN32_DCOM 

//vc6的bug.所以没用使用标准stl..
#include 
#include 
//using namespace std;
//com组件
#include 
#include 
# pragma comment(lib, "wbemuuid.lib") //链接lib

int main(int argc, char **argv)
{
    HRESULT hres; //定义COM调用的返回  HRESULT com返回类型

// Step 1: --------------------------------------------------
    // Initialize COM. ------------------------------------------

    hres =  CoInitializeEx(0, COINIT_MULTITHREADED); 
    if (FAILED(hres))
    {
        cout << "Failed to initialize COM library. Error code = 0x" 
            << hex << hres << endl;
        return 1;                  // Program has failed.
    }

// Step 2: --------------------------------------------------
    // Set general COM security levels --------------------------
    // Note: If you are using Windows 2000, you need to specify -
    // the default authentication credentials for a user by using
    // a SOLE_AUTHENTICATION_LIST structure in the pAuthList ----
    // parameter of CoInitializeSecurity ------------------------
    //常规安全级别设置(不写系统会调用默认的)
    hres =  CoInitializeSecurity(
        NULL, 
        -1,                          // COM authentication
        NULL,                        // Authentication services
        NULL,                        // Reserved
        RPC_C_AUTHN_LEVEL_DEFAULT,   // Default authentication 
        RPC_C_IMP_LEVEL_IMPERSONATE, // Default Impersonation  
        NULL,                        // Authentication info
        EOAC_NONE,                   // Additional capabilities 
        NULL                         // Reserved
        );

                      
    if (FAILED(hres))
    {
        cout << "Failed to initialize security. Error code = 0x" 
            << hex << hres << endl;
        CoUninitialize();
        return 1;                    // Program has failed.
    }
    
// Step 3: ---------------------------------------------------
    // Obtain the initial locator to WMI -------------------------
    //创建一个CLSID_WebmLocator对象.
    IWbemLocator *pLoc = NULL;
    hres = CoCreateInstance(
        CLSID_WbemLocator,
        0, 
        CLSCTX_INPROC_SERVER, 
        IID_IWbemLocator, (LPVOID *) &pLoc);
 
    if (FAILED(hres))
    {
        cout << "Failed to create IWbemLocator object."
            << " Err code = 0x"
            << hex << hres << endl;
        CoUninitialize();
        return 1;                 // Program has failed.
    }

// Step 4: -----------------------------------------------------
    // Connect to WMI through the IWbemLocator::ConnectServer method
    //连接WMI
    IWbemServices *pSvc = NULL;

    // Connect to the root\cimv2 namespace with
    // the current user and obtain pointer pSvc
    // to make IWbemServices calls.
    hres = pLoc->ConnectServer(
         _bstr_t(L"ROOT\\CIMV2"), // Object path of WMI namespace
         NULL,                    // User name. NULL = current user
         NULL,                    // User password. NULL = current
         0,                       // Locale. NULL indicates current
         NULL,                    // Security flags.
         0,                       // Authority (e.g. Kerberos)
         0,                       // Context object 
         &pSvc                    // pointer to IWbemServices proxy
         );
    
    if (FAILED(hres))
    {
        cout << "Could not connect. Error code = 0x" 
             << hex << hres << endl;
        pLoc->Release();     
        CoUninitialize();
        return 1;                // Program has failed.
    }

    cout << "Connected to ROOT\\CIMV2 WMI namespace" << endl;


// Step 5: --------------------------------------------------
    // 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))
    {
        cout << "Could not set proxy blanket. Error code = 0x" 
            << hex << hres << endl;
        pSvc->Release();
        pLoc->Release();     
        CoUninitialize();
        return 1;               // Program has failed.
    }

// Step 6: --------------------------------------------------
    // Use the IWbemServices pointer to make requests of WMI ----
    //执行你的代码
    //以SELECT开头,后面跟要查询的属性名(字段名)(可使用通配符*),再跟FROM,后面跟你要查询的类的名字
    // 下面是获取操作版本信息的方式
    // For example, get the name of the operating system
    IEnumWbemClassObject* pEnumerator = NULL;
    hres = pSvc->ExecQuery(
        bstr_t("WQL"), 
//        bstr_t("SELECT * FROM Win32_OperatingSystem"),string到com的装箱,bstr类型
        bstr_t("SELECT * FROM Win32_Process"),
        WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY, 
        NULL,
        &pEnumerator);
    
    if (FAILED(hres))
    {
        cout << "Query for operating system name failed."
            << " Error code = 0x" 
            << hex << hres << endl;
        pSvc->Release();
        pLoc->Release();
        CoUninitialize();
        return 1;               // Program has failed.
    }

// Step 7: -------------------------------------------------
    // Get the data from the query in step 6 -------------------
    //枚举查询
    IWbemClassObject *pclsObj;
    ULONG uReturn = 0;  //无符号长整
    cout<<"ProcessID  :ProcessName"<Next(WBEM_INFINITE, 1, 
            &pclsObj, &uReturn);

        if(0 == uReturn)
        {
            break;
        }

        VARIANT vtProp;  //Variant 是一种特殊的数据类型,除了定长String数据及用户定义类型外,可以包含任何种类的数据。Variant 也可以包含Empty、Error、Nothing及Null等特殊值。可以用VarType函数或TypeName函数来决定如何处理 Variant 中的数据。
//         // Get the value of the Name property
//         hr = pclsObj->Get(L"Name", 0, &vtProp, 0, 0);
//         CString str(vtProp.bstrVal);
//      //        cout << " OS Name : " << str.GetBuffer(NULL) << endl;
//         cout << " Process+++: " << str.GetBuffer(NULL) << endl;
//         //cout << " OS Name : " << vtProp.bstrVal << endl;

        // Get the value of the Name property
        hr = pclsObj->Get(L"ProcessID", 0, &vtProp, 0, 0);
        cout <Get(L"Name", 0, &vtProp, 0, 0);
        CString str(vtProp.bstrVal);
        cout << ":" << str.GetBuffer(NULL) << endl;

        VariantClear(&vtProp);

        pclsObj->Release();
    }

// Cleanup
    // ========
    // 不要忘记释放COM对象.
    pSvc->Release();
    pLoc->Release();
    pEnumerator->Release();
//MSDN例子的错误
    if(!pclsObj)
        pclsObj->Release();
    CoUninitialize();

    return 0;   // Program successfully completed.
}```

在VC6下测试,有

fatal error C1083: Cannot open include file: 'wbemidl.h': No such file or directory```
即“wbemidl.h”头文件未找到,于是乎跑到C:/下搜索该文件,发现有两处存在:
C:/Program Files/Microsoft SDKs/Windows/v5.0/Include/WbemIdl.h
C:/Program Files/Microsoft SDKs/Windows/v6.0A/Include/WbemIdl.h

查找资料发现,普遍认为不能再VC6中使用VS2008中附带的SDK,微软对VC6支持的最新的SDK版本为"PlatformSDK_2003_February"
在CSDN找到了一篇博文。提到了神奇的在微软社区一篇帖子,帖中有人给出了"PlatformSDK_2003_February"的下载地址,引用如下:

Here are the direct links to the Febuary 2003 SDK (build 5.2.3790.0):

http://download.microsoft.com/download/platformsdk/sdk/update/win98mexp/en-us/3790.0/FULL/PSDK-FULL.1.cab 

http://download.microsoft.com/download/platformsdk/sdk/update/win98mexp/en-us/3790.0/FULL/PSDK-FULL.2.cab

http://download.microsoft.com/download/platformsdk/sdk/update/win98mexp/en-us/3790.0/FULL/PSDK-FULL.3.cab 

http://download.microsoft.com/download/platformsdk/sdk/update/win98mexp/en-us/3790.0/FULL/PSDK-FULL.4.cab 


http://download.microsoft.com/download/platformsdk/sdk/update/win98mexp/en-us/3790.0/FULL/PSDK-FULL.5.cab 

http://download.microsoft.com/download/platformsdk/sdk/update/win98mexp/en-us/3790.0/FULL/PSDK-FULL.6.cab 

http://download.microsoft.com/download/platformsdk/sdk/update/win98mexp/en-us/3790.0/FULL/PSDK-FULL.7.cab 

http://download.microsoft.com/download/platformsdk/sdk/update/win98mexp/en-us/3790.0/FULL/PSDK-FULL.8.cab 

http://download.microsoft.com/download/platformsdk/sdk/update/win98mexp/en-us/3790.0/FULL/PSDK-FULL.9.cab 

http://download.microsoft.com/download/platformsdk/sdk/update/win98mexp/en-us/3790.0/FULL/PSDK-FULL.10.cab 

http://download.microsoft.com/download/platformsdk/sdk/update/win98mexp/en-us/3790.0/FULL/PSDK-FULL.11.cab 

http://download.microsoft.com/download/platformsdk/sdk/update/win98mexp/en-us/3790.0/FULL/PSDK-FULL.12.cab 

http://download.microsoft.com/download/platformsdk/sdk/update/win98mexp/en-us/3790.0/FULL/PSDK-FULL.13.cab 

http://download.microsoft.com/download/platformsdk/sdk/update/win98mexp/en-us/3790.0/FULL/PSDK-FULL.bat

http://download.microsoft.com/download/platformsdk/sdk/update/win98mexp/en-us/3790.0/FULL/Extract.exe

You must download all files in the same directory. To extract the SDK on your HDD you must use the batch file. After extracting the SDK you can install it from your extraction directory. You can also burn it on a CD or DVD.

安装完成后,在VC的Options -> Directories页面中添加相关搜索路径,再次进行编译,结果再次报错,报错信息如下:

error C2065: 'CoInitializeSecurity' : undeclared identifier
error C2065: 'EOAC_NONE' : undeclared identifier```
这次应该不能是SDK的问题了,到SDK的Include目录安装路径"C:/Program Files/Microsoft SDK/include"中,搜索文本"CoInitializeSecurity",发现其定义在"OBJBASE.H"文件中,且使用一个预编译宏控制:

if (_WIN32_WINNT >= 0x0400 ) || defined(_WIN32_DCOM)

添加一行

define _WIN32_DCOM ```

遇到错误信息

error LNK2001: unresolved external symbol __endthreadex

解决方法如下:
在做MFC程序的时候,由于不是用MFC APPWizard生成的,所以在调试的时候就出现了标题和下面所示的错误了:

error LNK2001: unresolved external symbol __endthreadex

error LNK2001: unresolved external symbol __beginthreadex

error LNK2001: unresolved external symbol _main

Debug/Hello.exe : fatal error LNK1120: 3 unresolved externals

解决方法:

1、“Project”->“settings”->“c/c++”->“Catagory” 选择“Code Generation”

  “use run-time library”选择“debug multithreaded”

    此时确定一般解决问题,也有可能出现如下问题提示:

    error LNK2001: unresolved external symbol _main

    Debug/Hello.exe : fatal error LNK1120: 1 unresolved externals

    这是由于我们的程序现在默认的是控制台应用程序,我们MFC做的是windows的应用程序,当然会产生错误了。

    此时,进行第二步操作:

2、[Project] --> [Settings] --> 选择"Link"属性页,

   在Project Options中将/subsystem:console改成/subsystem:windows

   提示:在Project Options窗口,右边滑动条向下滑动就会找到该项!

   进行以上两步操作后,问题解决!

参考:
1、Getting Information from WMI in Visual C++
http://www.codeproject.com/KB/system/Using_WMI_in_Visual_C__.aspx
2、Microsoft Platform SDK - February 2003,用VC6的不能不知道的事件
http://blog.csdn.net/citysheep/archive/2007/12/28/1996048.aspx
3、【收藏】通过 WMI 获取系统信息
http://www.zaoxue.com/article/tech-44714.htm
4、where download sdk server 2003 february edition ?
http://social.msdn.microsoft.com/Forums/zh-CN/windowssdk/thread/83205c43-ef46-447d-ae54-92bbeb543c38
5、http://blog.csdn.net/tzxx/article/details/6385292
6、http://blog.csdn.net/wangjieest/article/details/7320572

你可能感兴趣的:(VC6调用WMI编程——平台搭建)