我有一个纯C应用程序,它向我的适配器驱动程序发出IOCTL调用并显示信息,然而这是使用Visual Developer Studio 5(非托管代码)编译的......我需要从我的适配器获取一些信息WMI ....我的谷歌搜索努力表明,我需要使用COM编写一个C ++应用程序来实现与wMI或C#与.NET应用程序的任何形式的通信 a)情况确实如此吗?我的C应用程序无法解决问题? b)如果以上情况属实,那么我需要进行项目/ wp /工作区设置的最低级别更改是什么?
由于 索姆
答案 0 :(得分:13)
您可以从C调用COM。语法不如C ++友好,但它有效。 COM最初设计为使用C或C ++,COM和WMI头文件中包含本机C语言支持。它会很长...你的程序将负责分配所有必要的对象,检查每个COM调用的错误条件,以及释放它实例化的对象。
在使用用C ++编写的文档时,请转换以下形式的COM调用:
pSomething->Method(arg1, ...); // C++
为:
pSomething->lpVtbl->Method(pSomething, arg1, ...); // C
下面是我可以从WMI中实际提取一些信息的最短C代码。如果成功,它应列出计算机上的处理器以及以MHz为单位的时钟频率。该程序负责处理它分配的资源,但它没有任何错误检查(你应该在继续每一步之前查看这些hr值)。
这是一个visual studio 2008“Win32控制台应用程序”,主文件重命名为.c扩展名,删除了额外的stdafx文件。要使程序链接,请确保在项目属性中的Configuration Properties / Linker / Input / Additional Dependencies下包含wbemuuid.lib。它在我的Vista盒子上成功运行。
#define _WIN32_WINNT 0x0400
#define _WIN32_DCOM
#include <stdio.h>
#include <tchar.h>
#include <windows.h>
#include <wbemidl.h>
void _tmain(int argc, _TCHAR* argv[])
{
// result code from COM calls
HRESULT hr = 0;
// COM interface pointers
IWbemLocator *locator = NULL;
IWbemServices *services = NULL;
IEnumWbemClassObject *results = NULL;
// BSTR strings we'll use (http://msdn.microsoft.com/en-us/library/ms221069.aspx)
BSTR resource = SysAllocString(L"ROOT\\CIMV2");
BSTR language = SysAllocString(L"WQL");
BSTR query = SysAllocString(L"SELECT * FROM Win32_Processor");
// initialize COM
hr = CoInitializeEx(0, COINIT_MULTITHREADED);
hr = CoInitializeSecurity(NULL, -1, NULL, NULL, RPC_C_AUTHN_LEVEL_DEFAULT, RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_NONE, NULL);
// connect to WMI
hr = CoCreateInstance(&CLSID_WbemLocator, 0, CLSCTX_INPROC_SERVER, &IID_IWbemLocator, (LPVOID *) &locator);
hr = locator->lpVtbl->ConnectServer(locator, resource, NULL, NULL, NULL, 0, NULL, NULL, &services);
// issue a WMI query
hr = services->lpVtbl->ExecQuery(services, language, query, WBEM_FLAG_BIDIRECTIONAL, NULL, &results);
// list the query results
if (results != NULL) {
IWbemClassObject *result = NULL;
ULONG returnedCount = 0;
// enumerate the retrieved objects
while((hr = results->lpVtbl->Next(results, WBEM_INFINITE, 1, &result, &returnedCount)) == S_OK) {
VARIANT name;
VARIANT speed;
// obtain the desired properties of the next result and print them out
hr = result->lpVtbl->Get(result, L"Name", 0, &name, 0, 0);
hr = result->lpVtbl->Get(result, L"MaxClockSpeed", 0, &speed, 0, 0);
wprintf(L"%s, %dMHz\r\n", name.bstrVal, speed.intVal);
// release the current result object
result->lpVtbl->Release(result);
}
}
// release WMI COM interfaces
results->lpVtbl->Release(results);
services->lpVtbl->Release(services);
locator->lpVtbl->Release(locator);
// unwind everything else we've allocated
CoUninitialize();
SysFreeString(query);
SysFreeString(language);
SysFreeString(resource);
}
答案 1 :(得分:2)
另一个选项是,如果要保持对现有C应用程序的影响较小,那就是编写一个DLL,在内部可以使用C ++和COM包装类来查询所需的WMI信息。
此DLL可以提供纯C接口以适应您的应用程序。这就是我想要的方式。