WMI系统管理工具介绍和获取机器码

自己开发了一个股票智能分析软件,功能很强大,需要的点击下面的链接获取:

https://www.cnblogs.com/bclshuai/p/11380657.html

WMI系统管理工具获取机器码

 

目录

1      简介

2      WMI结构流程

3      WMI函数调用步骤和实例

3.1     函数调用步骤

3.2     获取代码实例

4      高级查询

 

 

1       简介

WMI(Windows Management Instrumentation)是window系统管理工具,是一个提供信息查询的服务,可以在服务中查看。WMI简单的应用就是获取CPU序列号,硬盘序列号,网卡mac地址等。查询正在运行的进程、线程信息,查询环境变量、驱动信息、文件夹属性、系统信息、系统服务、本地用户和组、查询硬件信息等。高级应用是通过WMI脚本或者应用程序去管理本地或者远程计算机上的资源。

 

 

 

WMI实际上是提供了一套标准规范的接口,提供给调用者使用,实现系统信息和资源的管理,它提供了一个通过操作系统、网络和企业环境去管理本地或远程计算机的统一接口集。不是直接通过调用系统API去访问,是因为系统API有些是不支持远程调用和脚本调用。WMI提供了通用化的接口。

       WMI支持WEBEM行业标准,WBEM即Web-Based Enterprise Management。WMI技术影响最大是其组件CIM和MOF。CIM是Common Information Modal,即公共信息模型。MOF是Managed Object Format,即托管对象格式。

 

2       WMI结构流程

如下图所示WMI相当于提供者和消费者之间的纽带,消费者调用WMI的API函数,去向提供者查询数据。

 

 

 

WMI Consumers(WMI使用者)

程序员通过各种形式,调用WMI的接口,请求查询数据。

WMI Infrastructure(WMI基础结构)

包含两个模块:包含WMI Core(WMI核心)的WMI Service(WMI服务)(Winmgmt)和WMI Repository(WMI存储库)。WMI存储库是通过WMI Namespace(WMI命名空间)组织起来的。在系统启动时,WMI服务会创建诸如root\default、root\cimv2和root\subscription等WMI命名空间。通过访问这些命名空间去获取其下定义的数据。

Managed object and WMI providers

硬盘驱动器、网络适配器、数据库系统、操作系统、进程或者服务等提供者通过MOF托管对象格式向WMI提供数据。

 

3       WMI函数调用步骤和实例

3.1  函数调用步骤

(1)   初始化COM based API

CoInitializeEx(

    _In_opt_ LPVOID pvReserved,

    _In_ DWORD dwCoInit

    );

(2)设置Com访问权限

CoInitializeSecurity(

    _In_opt_ PSECURITY_DESCRIPTOR pSecDesc,

    _In_ LONG cAuthSvc,

    _In_reads_opt_(cAuthSvc) SOLE_AUTHENTICATION_SERVICE * asAuthSvc,

    _In_opt_ void * pReserved1,

    _In_ DWORD dwAuthnLevel,

    _In_ DWORD dwImpLevel,

    _In_opt_ void * pAuthList,

    _In_ DWORD dwCapabilities,

    _In_opt_ void * pReserved3

);

(3)创建本地comlocator对象连接WMI服务

_Check_return_ HRESULT CoCreateInstance(

        _In_ REFCLSID rclsid,

        _Inout_opt_ LPUNKNOWN pUnkOuter = NULL,

        _In_ DWORD dwClsContext = CLSCTX_ALL) throw()

    {

        ATLASSERT(p == NULL);

        return ::CoCreateInstance(rclsid, pUnkOuter, dwClsContext, __uuidof(T), (void**)&p);

}

(4)连接WMI服务

   virtual HRESULT STDMETHODCALLTYPE ConnectServer(

            /* [in] */ const BSTR strNetworkResource,

            /* [in] */ const BSTR strUser,

            /* [in] */ const BSTR strPassword,

            /* [in] */ const BSTR strLocale,

            /* [in] */ long lSecurityFlags,

            /* [in] */ const BSTR strAuthority,

            /* [in] */ IWbemContext *pCtx,

            /* [out] */ IWbemServices **ppNamespace) = 0;

(5)执行查询语句查询数据

virtual HRESULT STDMETHODCALLTYPE ExecQuery(

            /* [in] */ __RPC__in const BSTR strQueryLanguage,

            /* [in] */ __RPC__in const BSTR strQuery,

            /* [in] */ long lFlags,

            /* [in] */ __RPC__in_opt IWbemContext *pCtx,

            /* [out] */ __RPC__deref_out_opt IEnumWbemClassObject **ppEnum) = 0;

3.2  获取代码实例

// WmiConnect.cpp : Defines the entry point for the console application.

//

 

#include "stdafx.h"

#include <atlcomcli.h>//CComPtr

#include <Wbemidl.h>

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

#include<iostream>

#include <sstream>

#define SQL_BUFF_SIZE 256

LPCWSTR const NETWORK_ADAPTER = L"Win32_NetworkAdapter";

LPCWSTR const BASE_BOARD = L"Win32_BaseBoard";

LPCWSTR const WIN32_CPU = L"Win32_Processor";

LPCWSTR const DISK_DRIVE = L"Win32_DiskDrive";

using namespace std;

//web服务对象

CComPtr<IWbemServices> m_spWbemServices = NULL;

//去除空格函数

void Trim(char* buf, size_t iSize, char cFlag)

{

    if (NULL == buf || iSize <= 0)

    {

        return;

    }

    //寻找前面的

    size_t iStart = 0, iEnd = 0;

    for (iStart = 0; iStart < iSize; iStart++)

    {

        if (buf[iStart] != cFlag)

        {

             break;

        }

    }

    if (iStart >= iSize)//全是

    {

        buf[0] = '\0';

        return;

    }

 

    //寻找后面的,发现要去除的符号时,直接改为字符结束符

    for (iEnd = iSize - 2; iEnd >= iStart; iEnd--)//排除结束符

    {

        if (buf[iEnd] != cFlag)

        {

             break;

        }

        else

        {

             buf[iEnd] = '\0';

        }

    }

 

    if (iEnd < 0)//全是

    {

        buf[0] = '\0';

        return;

    }

 

    if (iStart == 0)//前面没有要去除的符号时

    {

        return;

    }

 

    //移动数据

    size_t i = 0;

    for (size_t j = iStart; i <= iEnd - iStart; i++, j++)

    {

 

        buf[i] = buf[j];

    }

    buf[i] = '\0';//添加字符串结束标识

 

}

 

void Trim(string &str, char cFlag)

{

    if (str.length() == 0)

    {

        return;

    }

    if (str == " ")

    {

        str = "";

        return;

    }

    char *pBuf = new char[str.length() + 1];

    if (NULL != pBuf)

    {

        strcpy_s(pBuf, str.length() + 1, str.c_str());

        Trim(pBuf, str.length() + 1, cFlag);

        str = pBuf;

        delete[]pBuf;

    }

}

//将varValue变量转换为string

void VTtoStr(CComVariant & varValue, string &str)

{

    USES_CONVERSION;

    ostringstream oss;

    switch (varValue.vt)

    {

    case VT_I4:

        oss << varValue.lVal;

        break;

    case VT_I8:

        oss << varValue.llVal;

        break;

    case VT_I2:

        oss << varValue.iVal;

        break;

    case VT_UI1:

        oss << varValue.bVal;

        break;

    case VT_R4:

        oss << varValue.fltVal;

        break;

    case VT_R8:

        oss << varValue.dblVal;

        break;

    case VT_I1:

        oss << varValue.cVal;

        break;

    case VT_UI2:

        oss << varValue.uiVal;

        break;

    case VT_UI4:

        oss << varValue.ulVal;

        break;

    case VT_UI8:

        oss << varValue.ullVal;

        break;

    case VT_BOOL:

        oss << varValue.boolVal;

        break;

    case  VT_BSTR:

        oss << OLE2A(varValue.bstrVal);

        break;

    case VT_EMPTY:

        oss << "VT_EMPTY";

        break;

    case VT_CY:

        oss << "VT_CY";

        break;

    case VT_NULL:

        oss << "VT_NULL";

        break;

    case VT_DATE:

        oss << "VT_DATE";

        break;

    default:

        oss << (varValue.ChangeType(VT_BSTR) == S_OK) ? OLE2A(varValue.bstrVal) : "Cannot handle the the data type";

        break;

    }

    str = oss.str();

    Trim(str,' ');

}

//从查询的数据中获取属性值

string GetProperty(IWbemClassObject *pClassObject, LPCWSTR wsName)

{

    USES_CONVERSION;

    CComVariant varValue;

    string str("");

    if (pClassObject->Get(wsName, 0, &varValue, NULL, 0) != S_OK)

    {

        //LOG_INFO("Get fail");

        return str;

    }

    // 对不同的数据类型分别处理

    if (varValue.vt == VT_ARRAY) //数组

    {

        long iLowBound = 0, iUpBound = 0, j = 0;

        SafeArrayGetLBound(varValue.parray, 1, &iLowBound);

        SafeArrayGetUBound(varValue.parray, 1, &iUpBound);

        for ( /*long*/ j = iLowBound; j <= iUpBound; j++)

        {

             VARIANT *pvar = NULL;

             long temp = j;

             if (SafeArrayGetElement(varValue.parray, &temp, pvar) == S_OK && pvar)

             {

                 CComVariant varTemp;

                 if (varTemp.ChangeType(VT_BSTR, pvar) == S_OK)

                 {

                     if (0 != str.length())

                     {

                         str.append(",");

                     }

                     str.append(OLE2A(varTemp.bstrVal));

                 } //if( varTemp...

            } //if( SafeArrayGet...

             else

             {

                 //LOG_INFO("SafeArrayGetElement fail pvar=%p", pvar);

             }

        } //for( long j=iLowBound;...

    } //if (varValue.vt ...

    else

    {

        VTtoStr(varValue, str);

    }

//  LOG_INFO("%s = %s", OLE2A(wsName), str.c_str());

    return str;

}

//执行查询语句

bool ExecQuery(WCHAR* szSQL, CComPtr<IEnumWbemClassObject> &spEnumWbemClassObject)

{

    if (m_spWbemServices->ExecQuery(L"WQL", szSQL, WBEM_FLAG_RETURN_IMMEDIATELY, NULL, &spEnumWbemClassObject) != S_OK)

    {

        return false;

    }

    if (spEnumWbemClassObject->Reset() != S_OK)

    {

        return false;

    }

    return true;

}

BOOL GetWmiInfo(LPCWSTR lpszClass, LPCWSTR szProperty, string &szRet)

{

    BOOL bRet = FALSE;

    CComPtr<IEnumWbemClassObject> spEnumWbemClassObject;

    wchar_t szSQL[SQL_BUFF_SIZE] = { 0 };

    swprintf_s(szSQL, SQL_BUFF_SIZE - 1, L"Select %s from %s", szProperty, lpszClass);

 

    if (!ExecQuery(szSQL, spEnumWbemClassObject))

    {

        return FALSE;

    }

 

    USES_CONVERSION;

    ULONG uCount = 1, uReturned = 0;

    CComPtr<IWbemClassObject> spClassObject;

 

    while (spEnumWbemClassObject->Next(WBEM_INFINITE, uCount, &spClassObject, &uReturned) == S_OK)

    {

        szRet = GetProperty(spClassObject, szProperty);

        bRet = szRet.length() == 0 ? FALSE : TRUE;

        spClassObject.Release();

 

    }

    return bRet;

}

int main()

{

    HRESULT hResult;

    //初始化Com based API

    hResult = CoInitializeEx(0, COINIT_MULTITHREADED);

    if (FAILED(hResult))

    {

        cout << "Failed to initialize COM library. Error code = 0x"<< hex << hResult << endl;

        return 1; //

    }

    //设置Com访问权限

    hResult = CoInitializeSecurity(NULL, -1, NULL, NULL, RPC_C_AUTHN_LEVEL_PKT, RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_NONE, 0);

    if (S_OK != hResult && RPC_E_TOO_LATE != hResult)

    {

        cout<<"CoInitializeSecurity failed " << hResult<< endl;

        return 2;

    }

    //创建本地comlocator对象连接WMI服务

    CComPtr<IWbemLocator> pCom = NULL;

    hResult = pCom.CoCreateInstance(CLSID_WbemAdministrativeLocator, 0, CLSCTX_INPROC_SERVER | CLSCTX_LOCAL_SERVER);

    if (hResult != S_OK)

    {

        cout << "CoCreateInstance failed " << hResult << endl;

        CoUninitialize();

        return 3;

    }

    //连接WMI服务

    hResult = pCom->ConnectServer(L"root\\cimv2", NULL, NULL, NULL, 0, NULL, NULL, &m_spWbemServices);

    if (hResult != S_OK)

    {

        cout << "ConnectServer failed " << hResult << endl;

        CoUninitialize();

        return 3;

    }

    string szRet = "";

    //获取数据

    GetWmiInfo(L"Win32_DiskDrive", L"SerialNumber", szRet);//硬盘序列号

    cout << szRet << endl;

    GetWmiInfo(L"Win32_BaseBoard", L"SerialNumber", szRet);//主板序列号

    cout << szRet << endl;

    GetWmiInfo(L"Win32_Processor", L"ProcessorId", szRet);//cpu编号

    cout << szRet << endl;

    GetWmiInfo(L"Win32_PhysicalMemory", L"SerialNumber", szRet);//物理内存序列号

    cout << szRet << endl;

    GetWmiInfo(L"Win32_NetworkAdapter", L"MACAddress", szRet);//mac地址

    cout << szRet << endl;

    system("pause");

 

}

 

输出结果

 

 

 

 

4       高级查询

参考文献:

https://fangliang.blog.csdn.net/article/details/50644688?utm_medium=distribute.pc_relevant.none-task-blog-searchFromBaidu-3.control&depth_1-utm_source=distribute.pc_relevant.none-task-blog-searchFromBaidu-3.control

通过上面的实例可以看到,通过初始化,创建COM对象,连接服务之后,就可以通过执行类似于SQL的语句去查询数据,所以只要知道怎么去组织这个查询语句,然后调用ExecQuery函数,就可以查询数据了。下面列举一些常规的查询语句。可以组合查询下面的属性,用逗号隔开,也可以查询满足条件的属性,和SQL语句一致。

查询信息

属性

说明

查询进程Win32_Process的属性

SELECT Caption, ProcessId  FROM Win32_Process where processId=112313

Caption

名称

ProcessId

进程Id

ParentProcessId

父进程id

CommandLine

启动命令行

CreationDate

启动时间

ExecutablePath

进程路径

UserModeTime

用户时间

KernelModeTime

内核时间

ThreadCount

进程中线程数量

Priority

优先级

查询线程的属性Win32_Thread

SELECT * FROM Win32_Thread

ElapsedTime

线程占用时间

Handle

线程句柄

KernelModeTime

内核时间

Priority

优先级

查询环境变量

SELECT VariableValue FROM Win32_Environment WHERE SystemVariable = TRUE

VariableValue

变量值

根据用户名查询用户桌面Win32_Desktop

SELECT IconTitleSize FROM Win32_Desktop WHERE Name = 'Your Login Name’

IconTitleFaceName

桌面图标名称

IconTitleSize

字体大小

查询驱动信息Win32_SystemDriver

 

 

查询文件夹属性Win32_Directory

 

 

查询磁盘分区Win32_DiskPartition和Win32_LogicalDisk

 

 

查询系统属性Win32_ComputerSystem

 

 

查询系统时间Win32_LocalTime和Win32_UTCTime

 

 

查询服务Win32_Service

 

 

查询组和用户Win32_Group和Win32_UserAccount

 

 

查询主板信息Win32_BaseBoard

 

 

查询硬盘信息Win32_DiskDrive

 

 

查询内存信息Win32_MemoryDevice

 

 

查询网卡信息Win32_NetworkAdapter

 

 

查询CPU信息Win32_Processor

 

 

posted @   一字千金  阅读(897)  评论(0编辑  收藏  举报
编辑推荐:
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
阅读排行:
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
点击右上角即可分享
微信分享提示