VC之获得系统安装的反病毒软件[Using WMI in C++]

社区服务
高级搜索
猴岛论坛电脑百科VC之获得系统安装的反病毒软件[Using WMI in C++]
发帖 回复
倒序阅读 最近浏览的帖子最近浏览的版块
1个回复

VC之获得系统安装的反病毒软件[Using WMI in C++]

楼层直达
不懂也不知道

ZxID:10586231

等级: 禁止发言

举报 只看楼主 使用道具 楼主   发表于: 2010-07-17 0
VC之获得系统安装的反病毒软件[Using WMI in C++]
你需要一点点的VBS基础,WMI了解常识,COM接口皮毛就行。

今天的问题是,如何获得系统中安装的杀毒软件?有人会说遍历注册表之类的。其实用不着这么麻烦。每个正式的AV(Anti-Virus)软件,都要向系统注册自己。通过查看WMI中的\root\SecurityCenter这个名称空间,我们就能知道其中装了那些反病毒产品。

我们来看一段Vbs代码:

strComputer = "." 
Set objComputer = CreateObject("Shell.LocalMachine") 
Set oWMI = GetObject("winmgmts:\\" & strComputer & "\root\SecurityCenter") 
Set colAV = oWMI.ExecQuery("Select * from AntiVirusProduct") 
  For Each objAntiVirusProduct In colAV 
  If IsNull(objAntiVirusProduct.instanceGuid) Then 
    strSubject = "Anti-virus is not running on " & objComputer.MachineName 
    strTextbody = "You will need to check on " & objComputer.MachineName   
    Call SmtpServer   
  Else 
    strCompany = objAntiVirusProduct.companyName 
    strAV = objAntiVirusProduct.displayName 
    strScanning = objAntiVirusProduct.onAccessScanningEnabled 
    strUptodate = objAntiVirusProduct.productUptoDate 
strComputer = "."
Set objComputer = CreateObject("Shell.LocalMachine")
Set oWMI = GetObject("winmgmts:\\" & strComputer & "\root\SecurityCenter")
Set colAV = oWMI.ExecQuery("Select * from AntiVirusProduct")
  For Each objAntiVirusProduct In colAV
  If IsNull(objAntiVirusProduct.instanceGuid) Then
    strSubject = "Anti-virus is not running on " & objComputer.MachineName
    strTextbody = "You will need to check on " & objComputer.MachineName
    Call SmtpServer 
  Else
    strCompany = objAntiVirusProduct.companyName
    strAV = objAntiVirusProduct.displayName
    strScanning = objAntiVirusProduct.onAccessScanningEnabled
    strUptodate = objAntiVirusProduct.productUptoDate

如果以上代码你觉得很难懂的话,那么不推荐你继续看下去,请稍微补习下Vbs和Wmi相关的知识。

Select * from AntiVirusProduct是一条WQL语句,用来查询所有的反病毒软件,并返回一个集合。我们用WMITools里面的WMI CIM Studio进行查看下\root\SecurityCenter这个名称空间里面有哪些Win32 Class




在左边,看到了么,AntiVirusProduct。还有FireWallProduct,防火墙产品,本机没有防火墙,就用查看反病毒软件来做说明吧。

右边的呢,都是AntiVirusProduct这个类的属性(Properties)。里面有产品名,产品公司名,版本号等等。那么我现在需要的,就是通过C++获取到和Vbs一样的信息。上面的Vbs脚本不知道你执行过了么?

我们接下来看C++代码

#define _WIN32_DCOM 
 
#include <iostream> 
 
using namespace std; 
 
#include <comdef.h> 
 
#include <Wbemidl.h> 
 
 
# pragma comment(lib, "wbemuuid.lib") 
 
 
int main(int argc, char **argv) 
 

 
    HRESULT hres; 
 
 
    // 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 -------------------------- 
 
 
    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 ------------------------- 
 
 
    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 
 
 
    IWbemServices *pSvc = NULL; 
 
    // Connect to the root\SecurityCenter namespace with 
 
    // the current user and obtain pointer pSvc 
 
    // to make IWbemServices calls. 
 
    hres = pLoc->ConnectServer( 
 
        _bstr_t(L"ROOT\\SecurityCenter"), // 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\\SecurityCenter 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 ---- 
 
 
    // For example, get the name of the operating system 
 
    IEnumWbemClassObject* pEnumerator = NULL; 
 
    hres = pSvc->ExecQuery( 
 
        bstr_t("WQL"),   
 
        bstr_t("SELECT * FROM AntiVirusProduct"), 
 
        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; 
 
 
    while (pEnumerator) 
 
    { 
 
        HRESULT hr = pEnumerator->Next(WBEM_INFINITE, 1,   
 
            &pclsObj, &uReturn); 
 
 
        if(0 == uReturn) 
 
        { 
 
            break; 
 
        } 
 
 
        VARIANT vtProp; 
 
 
        // Get the value of the Name property 
 
        hr = pclsObj->Get(L"displayName", 0, &vtProp, 0, 0); 
 
        wcout << "AV  Product displayName : " << vtProp.bstrVal << endl; 
 
        hr = pclsObj->Get(L"companyName", 0, &vtProp, 0, 0); 
 
        wcout << "AV  Product companyName : " << vtProp.bstrVal << endl; 
 
        hr = pclsObj->Get(L"pathToSignedProductExe", 0, &vtProp, 0, 0); 
 
        wcout << "AV  Product pathToSignedProductExe : " << vtProp.bstrVal << endl;           
 
        hr = pclsObj->Get(L"versionNumber", 0, &vtProp, 0, 0); 
 
        wcout << "AV  Product versionNumber : " << vtProp.bstrVal << endl;             
 
        VariantClear(&vtProp);   
 
        pclsObj->Release(); 
 
    } 
 
 
    // Cleanup 
 
    // ======== 
 
 
    pSvc->Release(); 
 
    pLoc->Release(); 
 
    pEnumerator->Release(); 
 
    //pclsObj->Release(); 
 
    CoUninitialize(); 
 
 
    return 0;  // Program successfully completed. 
 

#define _WIN32_DCOM

#include <iostream>

using namespace std;

#include <comdef.h>

#include <Wbemidl.h>


# pragma comment(lib, "wbemuuid.lib")


int main(int argc, char **argv)

{

    HRESULT hres;


    // 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 --------------------------


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


    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


    IWbemServices *pSvc = NULL;

    // Connect to the root\SecurityCenter namespace with

    // the current user and obtain pointer pSvc

    // to make IWbemServices calls.

    hres = pLoc->ConnectServer(

        _bstr_t(L"ROOT\\SecurityCenter"), // 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\\SecurityCenter 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 ----


    // For example, get the name of the operating system

    IEnumWbemClassObject* pEnumerator = NULL;

    hres = pSvc->ExecQuery(

        bstr_t("WQL"),

        bstr_t("SELECT * FROM AntiVirusProduct"),

        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;


    while (pEnumerator)

    {

        HRESULT hr = pEnumerator->Next(WBEM_INFINITE, 1,

            &pclsObj, &uReturn);


        if(0 == uReturn)

        {

            break;

        }


        VARIANT vtProp;


        // Get the value of the Name property

        hr = pclsObj->Get(L"displayName", 0, &vtProp, 0, 0);

        wcout << "AV  Product displayName : " << vtProp.bstrVal << endl;

        hr = pclsObj->Get(L"companyName", 0, &vtProp, 0, 0);

        wcout << "AV  Product companyName : " << vtProp.bstrVal << endl;

        hr = pclsObj->Get(L"pathToSignedProductExe", 0, &vtProp, 0, 0);

        wcout << "AV  Product pathToSignedProductExe : " << vtProp.bstrVal << endl;       

        hr = pclsObj->Get(L"versionNumber", 0, &vtProp, 0, 0);

        wcout << "AV  Product versionNumber : " << vtProp.bstrVal << endl;         

        VariantClear(&vtProp);

        pclsObj->Release();

    }


    // Cleanup

    // ========


    pSvc->Release();

    pLoc->Release();

    pEnumerator->Release();

    //pclsObj->Release();

    CoUninitialize();


    return 0;  // Program successfully completed.

}

这份代码是我从MSDN中的C++ WMI例子中抠出来然后针对具体情况进行修改,所以并不能算是真正意义上的原创。但是呢,这个教材文章确实是原创的 (Tr0j4n *_*)
运行效果:


注释大部分都是微软加的,所以非常详细。它本来是用来查询ROOT\\CIMV2这个名称空间中的Win32_OperatingSystem类,然后获得操作系统的名称。说实话,用C++调用WMI就为了得到操作系统名称,这简直是一种浪费,简单的Win32 API调用就能实现了。所以我把它改成了查看本机的反病毒产品的代码。

C++操作WMI执行WQL返回,其实就是一个模板,所以我认为大家有掌握的必要。而且可以举一反三。

Step1:Initialize COM parameters with a call to CoInitializeEx.
For more information, see Initializing COM for a WMI Application.

Step2:Initialize COM process security by calling CoInitializeSecurity.
Windows 2000:  Specify the default authentication credentials for a user by using a SOLE_AUTHENTICATION_LIST structure in the pAuthList parameter of CoInitializeSecurity.
For more information, see Setting the Default Process Security Level Using C++.

Step3:Obtain the initial locator to WMI by calling CoCreateInstance.
For more information, see Creating a Connection to a WMI Namespace.

Step4:Obtain a pointer to IWbemServices for the root\cimv2 namespace on the local computer by calling IWbemLocator::ConnectServer. To connect to a remote computer, see Example: Getting WMI Data from a Remote Computer.
For more information, see Creating a Connection to a WMI Namespace.

Step5:Set IWbemServices proxy security so the WMI service can impersonate the client by calling CoSetProxyBlanket.
For more information, see Setting the Security Levels on a WMI Connection.

Step6:Use the IWbemServices pointer to make requests of WMI. This example executes a query for the name of the operating system by calling IWbemServices::ExecQuery.
The following WQL query is one of the method arguments.

SELECT * FROM Win32_OperatingSystem  这就是WQL语句

The result of this query is stored in an IEnumWbemClassObject pointer. This allows the data objects from the query to be retrieved semisynchronously with the IEnumWbemClassObject interface. For more information, see Enumerating WMI. For getting the data asynchronously, see Example: Getting WMI Data from the Local Computer Asynchronously.
For more information about making requests to WMI, see Manipulating Class and Instance Information, Querying WMI, and Calling a Method.

Step7:Get and display the data from the WQL query. The IEnumWbemClassObject pointer is linked to the data objects that the query returned, and the data objects can be retrieved with the IEnumWbemClassObject::Next method. This method links the data objects to an IWbemClassObject pointer that is passed into the method. Use the IWbemClassObject::Get method to get the desired information from the data objects.

以上解释出自MSDN。MSDN用得好,对编程能力是一个很大的帮助。如果觉得英语不行,只能去恶补咯。

其实,关键在4,6,7步。第四步弄的是名称空间,第六步写的是WQL语句,第七步获得返回值。至于第七步。你对比那个While循环中的C++语句,和文章开头的Vbs语句中的For each对比,你看出了什么名堂了吗?

Vbs通过For each枚举类实例,而C++中通过IEnumWbemClassObject接口指针。

如何获得IEnumWbemClassObject接口指针呢?微软告诉我们有4种方法。我用的是第一种,执行一个WQL语句,获得一个AntiVirusProduct类实例的枚举接口指针。

IWbemServices::ExecQuery
IWbemServices::CreateInstanceEnum
IWbemServices::CreateClassEnum
IWbemServices::ExecNotificationQuery

我是怎么实现变量的呢?我用的是枚举接口指针的Next方法,其实它还有别的方法,比如Skip跳过,NextAsync异步下一个。

今后有什么WMI的代码想在VC中实现,只要按这个模板一套用,属于你自己的C++ WMI代码就出炉的。对C++ WMI编程感兴趣的同学,可以参考 这里
本帖de评分: 1 条评分 DB +6
DB+6

我很赞同

不懂也不知道

ZxID:10586231

等级: 禁止发言

举报 只看该作者 沙发   发表于: 2010-07-17 0
有些深奥的 慢慢看。直得我门去看纳
« 返回列表
发帖 回复