Skip to content

pdh.go alway get incorrect data #12

Open
@oliveagle

Description

@oliveagle
#python pseudocode
hQuery = win32pdh.OpenQuery()
hCounter = win32pdh.AddCounter(hQuery, "\System\Processes")
win32pdh.CollectQueryData(hQuery)
win32pdh.CollectQueryData(hQuery)
_, val = win32pdh.GetFormattedCounterValue(hCounter, win32pdh.PDH_FMT_DOUBLE)
print val

Code above will get processes count of windows. which usually in my system is around 60

but with pdh.go version I always get meaningless data. here is my code:

// +build windows
package main

import (
    "fmt"
    "github.com/kr/pretty"
    "github.com/lxn/win"
)

func main() {
    var handle win.PDH_HQUERY
    var counterHandle win.PDH_HCOUNTER
    ret := win.PdhOpenQuery(0, 0, &handle)
    ret = win.PdhAddEnglishCounter(handle, "\\System\\Processes", 0, &counterHandle)

    var derp win.PDH_FMT_COUNTERVALUE_DOUBLE

    ret = win.PdhCollectQueryData(handle)

    var lpdwType *uint32

    fmt.Printf("Collect return code is %x\n", ret) // return code will be PDH_CSTATUS_INVALID_DATA
    ret = win.PdhGetFormattedCounterValueDouble(counterHandle, lpdwType, &derp)
    pretty.Println(derp)

    ret = win.PdhCollectQueryData(handle)
    fmt.Printf("Collect return code is %x\n", ret) // return code will be ERROR_SUCCESS
    ret = win.PdhGetFormattedCounterValueDouble(counterHandle, lpdwType, &derp)
    pretty.Println(derp)
}

here is the output
qq20150211-1

after some dig on this. I found out a solution: pass in a c struct instead of go struct

here is the code:

/*
typedef struct _PDH_FMT_COUNTERVALUE_DOUBLE
{
    int CStatus;
    double DoubleValue;
}PDH_FMT_COUNTERVALUE_DOUBLE;
*/
import "C"

func main(){
    // ...

    var pValue C.PDH_FMT_COUNTERVALUE_DOUBLE

    r1, r2, err = syscall.Syscall6(uintptr(PdhGetFormattedCounterValue), 4,
        uintptr(phCounter),
        uintptr(PDH_FMT_DOUBLE),
        uintptr(lpdwType),
        uintptr(unsafe.Pointer(&pValue)),
        0, 0)
    fmt.Println(r1, r2, err)
    fmt.Println(lpdwType, pValue, pValue.DoubleValue)
    pretty.Println(pValue)
}

qq20150211-3

I checked these counters they all give me correct data

    // path := syscall.StringToUTF16Ptr("\\System\\Processes")
    // path := syscall.StringToUTF16Ptr("\\LogicalDisk(C:)\\% Free Space")
    // path := syscall.StringToUTF16Ptr("\\Memory\\% Committed Bytes In Use")
    path := syscall.StringToUTF16Ptr("\\Memory\\Available MBytes")

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions