Skip to content

Commit

Permalink
use StackExchange/wmi instead of invoking wmic process.
Browse files Browse the repository at this point in the history
Note: This may not work on some old Windows XP.
  • Loading branch information
shirou committed Apr 19, 2015
1 parent b55d373 commit 64357f0
Show file tree
Hide file tree
Showing 4 changed files with 134 additions and 128 deletions.
34 changes: 0 additions & 34 deletions common/common_windows.go
Expand Up @@ -3,9 +3,6 @@
package common

import (
"fmt"
"os/exec"
"strings"
"syscall"
"unsafe"
)
Expand Down Expand Up @@ -75,37 +72,6 @@ func BytePtrToString(p *uint8) string {
return string(a[:i])
}

// exec wmic and return lines splited by newline
func GetWmic(target string, query ...string) ([][]string, error) {
cmd := []string{target}
cmd = append(cmd, query...)
cmd = append(cmd, "/format:csv")
out, err := exec.Command("wmic", cmd...).Output()
if err != nil {
return [][]string{}, err
}
lines := strings.Split(string(out), "\r\r\n")
if len(lines) <= 2 {
return [][]string{}, fmt.Errorf("wmic result malformed: [%q]", lines)
}
var ret [][]string
for _, l := range lines[2:] { // skip first two lines
var lr []string
for _, r := range strings.Split(l, ",") {
if r == "" {
continue
}
lr = append(lr, strings.TrimSpace(r))
}
if len(lr) != 0 {
ret = append(ret, lr)
}
}

return ret, nil

}

// CounterInfo
// copied from https://github.com/mackerelio/mackerel-agent/
type CounterInfo struct {
Expand Down
72 changes: 34 additions & 38 deletions cpu/cpu_windows.go
Expand Up @@ -3,14 +3,28 @@
package cpu

import (
"strconv"
"fmt"
"syscall"
"time"
"unsafe"

"github.com/StackExchange/wmi"

common "github.com/shirou/gopsutil/common"
)

type Win32_Processor struct {
LoadPercentage uint16
L2CacheSize uint32
Family uint16
Manufacturer string
Name string
NumberOfLogicalProcessors uint32
ProcessorId string
Stepping *string
MaxClockSpeed uint32
}

// TODO: Get percpu
func CPUTimes(percpu bool) ([]CPUTimesStat, error) {
var ret []CPUTimesStat
Expand Down Expand Up @@ -43,59 +57,41 @@ func CPUTimes(percpu bool) ([]CPUTimesStat, error) {

func CPUInfo() ([]CPUInfoStat, error) {
var ret []CPUInfoStat
lines, err := common.GetWmic("cpu", "get", "Family,L2CacheSize,Manufacturer,Name,NumberOfLogicalProcessors,ProcessorId,Stepping")
var dst []Win32_Processor
q := wmi.CreateQuery(&dst, "")
err := wmi.Query(q, &dst)
if err != nil {
return ret, err
}
for i, t := range lines {
cache, err := strconv.Atoi(t[2])
if err != nil {
cache = 0
}
cores, err := strconv.Atoi(t[5])
if err != nil {
cores = 0
}
stepping := 0
if len(t) > 7 {
stepping, err = strconv.Atoi(t[6])
if err != nil {
stepping = 0
}
}
for i, l := range dst {
cpu := CPUInfoStat{
CPU: int32(i),
Family: t[1],
CacheSize: int32(cache),
VendorID: t[3],
ModelName: t[4],
Cores: int32(cores),
PhysicalID: t[6],
Stepping: int32(stepping),
Family: fmt.Sprintf("%d", l.Family),
CacheSize: int32(l.L2CacheSize),
VendorID: l.Manufacturer,
ModelName: l.Name,
Cores: int32(l.NumberOfLogicalProcessors),
PhysicalID: l.ProcessorId,
Mhz: float64(l.MaxClockSpeed),
Flags: []string{},
}
ret = append(ret, cpu)
}

return ret, nil
}

func CPUPercent(interval time.Duration, percpu bool) ([]float64, error) {
ret := []float64{}

lines, err := common.GetWmic("cpu", "get", "loadpercentage")
var ret []float64
var dst []Win32_Processor
q := wmi.CreateQuery(&dst, "")
err := wmi.Query(q, &dst)
if err != nil {
return ret, err
}
for _, l := range lines {
if len(l) < 2 {
continue
}
p, err := strconv.Atoi(l[1])
if err != nil {
p = 0
}
// but windows can only get one percent.
ret = append(ret, float64(p)/100.0)
for _, l := range dst {
// use range but windows can only get one percent.
ret = append(ret, float64(l.LoadPercentage)/100.0)
}
return ret, nil
}
24 changes: 12 additions & 12 deletions host/host_windows.go
Expand Up @@ -3,11 +3,11 @@
package host

import (
"fmt"
"os"
"strings"
"time"

"github.com/StackExchange/wmi"

common "github.com/shirou/gopsutil/common"
process "github.com/shirou/gopsutil/process"
)
Expand All @@ -16,6 +16,10 @@ var (
procGetSystemTimeAsFileTime = common.Modkernel32.NewProc("GetSystemTimeAsFileTime")
)

type Win32_OperatingSystem struct {
LastBootUpTime time.Time
}

func HostInfo() (*HostInfoStat, error) {
ret := &HostInfoStat{}
hostname, err := os.Hostname()
Expand All @@ -40,19 +44,15 @@ func HostInfo() (*HostInfoStat, error) {
}

func BootTime() (uint64, error) {
lines, err := common.GetWmic("os", "get", "LastBootUpTime")
if err != nil {
return 0, err
}
if len(lines) == 0 || len(lines[0]) != 2 {
return 0, fmt.Errorf("could not get LastBootUpTime")
}
format := "20060102150405"
t, err := time.Parse(format, strings.Split(lines[0][1], ".")[0])
now := time.Now()

var dst []Win32_OperatingSystem
q := wmi.CreateQuery(&dst, "")
err := wmi.Query(q, &dst)
if err != nil {
return 0, err
}
now := time.Now()
t := dst[0].LastBootUpTime.Local()
return uint64(now.Sub(t).Seconds()), nil
}

Expand Down

0 comments on commit 64357f0

Please sign in to comment.