我想从Go运行WMI查询。有几种方法可以从Go 调用DLL函数。我的理解是,在某个地方必须有一些DLL,通过正确的调用,它将返回一些我可以解析和使用的数据。我宁愿避免调用C或C ++,尤其是因为我猜想它们是Windows API本身的包装。
我检查了的输出dumpbin.exe /exports c:\windows\system32\wmi.dll,以下条目看起来很有希望:
dumpbin.exe /exports c:\windows\system32\wmi.dll
WmiQueryAllDataA (forwarded to wmiclnt.WmiQueryAllDataA)
但是我不确定从这里做什么。此函数采用什么参数?它返回什么?搜索WmiQueryAllDataA没有帮助。并且该名称仅出现在的注释中c:\program files (x86)\windows kits\8.1\include\shared\wmistr.h,但没有函数签名。
WmiQueryAllDataA
c:\program files (x86)\windows kits\8.1\include\shared\wmistr.h
有更好的方法吗?还有另一个DLL吗?我想念什么吗?我应该只使用C包装器吗?
使用.NET Reflector在Linqpad中运行WMI查询显示了WmiNetUtilsHelper:ExecQueryWmi(和_f版本)的使用,但都没有可见的实现。
WmiNetUtilsHelper:ExecQueryWmi
_f
更新: 使用github.com/StackExchange/wmi软件包,该软件包在接受的答案中使用解决方案。
从C ++刚刚起步的新世纪开始,您就来到了COM的美好世界,即C语言中的面向对象编程。
在github上,mattn 在Go中集成了一个小包装,我曾经使用它包装了一个快速的示例程序。“ 这个存储库是为实验而创建的,应该被认为是不稳定的。 ”灌输了各种各样的信心。
我省去了很多错误检查。当我说时,请相信我,您将想要重新添加。
package main import ( "github.com/mattn/go-ole" "github.com/mattn/go-ole/oleutil" ) func main() { // init COM, oh yeah ole.CoInitialize(0) defer ole.CoUninitialize() unknown, _ := oleutil.CreateObject("WbemScripting.SWbemLocator") defer unknown.Release() wmi, _ := unknown.QueryInterface(ole.IID_IDispatch) defer wmi.Release() // service is a SWbemServices serviceRaw, _ := oleutil.CallMethod(wmi, "ConnectServer") service := serviceRaw.ToIDispatch() defer service.Release() // result is a SWBemObjectSet resultRaw, _ := oleutil.CallMethod(service, "ExecQuery", "SELECT * FROM Win32_Process") result := resultRaw.ToIDispatch() defer result.Release() countVar, _ := oleutil.GetProperty(result, "Count") count := int(countVar.Val) for i :=0; i < count; i++ { // item is a SWbemObject, but really a Win32_Process itemRaw, _ := oleutil.CallMethod(result, "ItemIndex", i) item := itemRaw.ToIDispatch() defer item.Release() asString, _ := oleutil.GetProperty(item, "Name") println(asString.ToString()) } }
真正的问题是对ExecQuery的调用,我碰巧从可用的类中获取Win32_Process,因为它易于理解和打印。
在我的机器上,将打印:
System Idle Process System smss.exe csrss.exe wininit.exe services.exe lsass.exe svchost.exe svchost.exe atiesrxx.exe svchost.exe svchost.exe svchost.exe svchost.exe svchost.exe spoolsv.exe svchost.exe AppleOSSMgr.exe AppleTimeSrv.exe ... and so on go.exe main.exe
我不是在提升运行状态或未禁用UAC的情况下运行,但某些WMI提供程序将需要特权用户。
我也不是100%不会漏掉一点,您需要深入研究一下。COM对象是按引用计数的,因此defer应该很合适(前提是该方法长期运行不会疯狂),但是go- ole可能有一些我没注意到的魔术。
defer