自己开发了一个股票智能分析软件,功能很强大,需要的点击下面的链接获取:
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服务会创建诸如rootdefault、rootcimv2和rootsubscription等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] = ' ';
return;
}
//寻找后面的,发现要去除的符号时,直接改为字符结束符
for (iEnd = iSize - 2; iEnd >= iStart; iEnd--)//排除结束符
{
if (buf[iEnd] != cFlag)
{
break;
}
else
{
buf[iEnd] = ' ';
}
}
if (iEnd < 0)//全是
{
buf[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] = ' ';//添加字符串结束标识
}
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 高级查询
参考文献:
通过上面的实例可以看到,通过初始化,创建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 |