dongtaijiao7140
2013-12-04 01:44
浏览 404
已采纳

从Go查询WMI

I would like to run WMI queries from Go. There are ways to call DLL functions from Go. My understanding is that there must be some DLL somewhere which, with the correct call, will return some data I can parse and use. I'd prefer to avoid calling into C or C++, especially since I would guess those are wrappers over the Windows API itself.

I've examined the output of dumpbin.exe /exports c:\windows\system32\wmi.dll, and the following entry looks promising:

WmiQueryAllDataA (forwarded to wmiclnt.WmiQueryAllDataA)

However I'm not sure what to do from here. What arguments does this function take? What does it return? Searching for WmiQueryAllDataA is not helpful. And that name only appears in a comment of c:\program files (x86)\windows kits\8.1\include\shared\wmistr.h, but with no function signature.

Are there better methods? Is there another DLL? Am I missing something? Should I just use a C wrapper?

Running a WMI query in Linqpad with .NET Reflector shows the use of WmiNetUtilsHelper:ExecQueryWmi (and a _f version), but neither have a viewable implementation.

Update: use the github.com/StackExchange/wmi package which uses the solution in the accepted answer.

图片转代码服务由CSDN问答提供 功能建议

我想从Go运行WMI查询。 有几种方法可以从Go中调用DLL函数。 我的理解是,在某个地方必须有一些DLL,通过正确的调用,它将返回一些我可以解析和使用的数据。 我宁愿避免调用C或C ++,尤其是因为我猜想它们是Windows API本身的包装器。

我已经检查了 dumpbin.exe的输出。 / exports c:\ windows \ system32 \ wmi.dll ,下面的条目看起来很有希望:

WmiQueryAllDataA(转发给wmiclnt.WmiQueryAllDataA)

但是我不确定从这里做什么。 此函数采用什么参数? 它返回什么? 搜索 WmiQueryAllDataA 没有帮助。 并且该名称仅出现在 c:\ program files(x86)\ windows kits \ 8.1 \ include \ shared \ wmistr.h 的注释中,但没有功能签名。

有更好的方法吗? 还有另一个DLL吗? 我想念什么吗? 我应该只使用C包装程序吗?

使用.NET Reflector在Linqpad中运行WMI查询显示了 WmiNetUtilsHelper:ExecQueryWmi (和 _f 版本),但都没有可见的实现。

更新:使用 github.com/StackExchange/wmi 软件包,该软件包在接受的答案中使用该解决方案。

  • 写回答
  • 好问题 提建议
  • 追加酬金
  • 关注问题
  • 邀请回答

3条回答 默认 最新

  • donglaoe2979 2013-12-04 04:00
    最佳回答

    Welcome to the wonderful world of COM, Object Oriented Programming in C from when C++ was "a young upstart".

    On github mattn has thrown together a little wrapper in Go, which I used to throw together a quick example program. "This repository was created for experimentation and should be considered unstable." instills all sorts of confidence.

    I'm leaving out a lot of error checking. Trust me when I say, you'll want to add it back.

    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())
        }
    }
    

    The real meat is the call to ExecQuery, I happen to grab Win32_Process from the available classes because it's easy to understand and print.

    On my machine, this prints:

    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
    

    I'm not running it elevated or with UAC disabled, but some WMI providers are gonna require a privileged user.

    I'm also not 100% that this won't leak a little, you'll want to dig into that. COM objects are reference counted, so defer should be a pretty good fit there (provided the method isn't crazy long running) but go-ole may have some magic inside I didn't notice.

    评论
    解决 无用
    打赏 举报
查看更多回答(2条)

相关推荐 更多相似问题