mirror of
https://github.com/shirou/gopsutil.git
synced 2025-04-26 13:48:59 +08:00
[host][windows] Completely remove slow wmi calls to retrieve OS version, use registry and RtlGetVersion
This commit is contained in:
parent
df331c7615
commit
eb11fd6e2f
@ -13,24 +13,32 @@ import (
|
||||
"time"
|
||||
"unsafe"
|
||||
|
||||
"github.com/StackExchange/wmi"
|
||||
"github.com/shirou/gopsutil/internal/common"
|
||||
process "github.com/shirou/gopsutil/process"
|
||||
"golang.org/x/sys/windows"
|
||||
"golang.org/x/sys/windows/registry"
|
||||
)
|
||||
|
||||
var (
|
||||
procGetSystemTimeAsFileTime = common.Modkernel32.NewProc("GetSystemTimeAsFileTime")
|
||||
procGetTickCount32 = common.Modkernel32.NewProc("GetTickCount")
|
||||
procGetTickCount64 = common.Modkernel32.NewProc("GetTickCount64")
|
||||
osInfo *Win32_OperatingSystem
|
||||
procRtlGetVersion = common.ModNt.NewProc("RtlGetVersion")
|
||||
)
|
||||
|
||||
type Win32_OperatingSystem struct {
|
||||
Version string
|
||||
Caption string
|
||||
ProductType uint32
|
||||
BuildNumber string
|
||||
// https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/content/wdm/ns-wdm-_osversioninfoexw
|
||||
type osVersionInfoExW struct {
|
||||
dwOSVersionInfoSize uint32
|
||||
dwMajorVersion uint32
|
||||
dwMinorVersion uint32
|
||||
dwBuildNumber uint32
|
||||
dwPlatformId uint32
|
||||
szCSDVersion [128]uint16
|
||||
wServicePackMajor uint16
|
||||
wServicePackMinor uint16
|
||||
wSuiteMask uint16
|
||||
wProductType uint8
|
||||
wReserved uint8
|
||||
}
|
||||
|
||||
func Info() (*InfoStat, error) {
|
||||
@ -113,25 +121,6 @@ func getMachineGuid() (string, error) {
|
||||
return hostID, nil
|
||||
}
|
||||
|
||||
func GetOSInfo() (Win32_OperatingSystem, error) {
|
||||
return GetOSInfoWithContext(context.Background())
|
||||
}
|
||||
|
||||
func GetOSInfoWithContext(ctx context.Context) (Win32_OperatingSystem, error) {
|
||||
var dst []Win32_OperatingSystem
|
||||
q := wmi.CreateQuery(&dst, "")
|
||||
ctx, cancel := context.WithTimeout(context.Background(), common.Timeout)
|
||||
defer cancel()
|
||||
err := common.WMIQueryWithContext(ctx, q, &dst)
|
||||
if err != nil {
|
||||
return Win32_OperatingSystem{}, err
|
||||
}
|
||||
|
||||
osInfo = &dst[0]
|
||||
|
||||
return dst[0], nil
|
||||
}
|
||||
|
||||
func Uptime() (uint64, error) {
|
||||
return UptimeWithContext(context.Background())
|
||||
}
|
||||
@ -179,18 +168,37 @@ func PlatformInformation() (platform string, family string, version string, err
|
||||
}
|
||||
|
||||
func PlatformInformationWithContext(ctx context.Context) (platform string, family string, version string, err error) {
|
||||
if osInfo == nil {
|
||||
_, err = GetOSInfo()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
// GetVersionEx lies on Windows 8.1 and returns as Windows 8 if we don't declare compatibility in manifest
|
||||
// RtlGetVersion bypasses this lying layer and returns the true Windows version
|
||||
// https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/content/wdm/nf-wdm-rtlgetversion
|
||||
// https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/content/wdm/ns-wdm-_osversioninfoexw
|
||||
var osInfo osVersionInfoExW
|
||||
osInfo.dwOSVersionInfoSize = uint32(unsafe.Sizeof(osInfo))
|
||||
ret, _, err := procRtlGetVersion.Call(uintptr(unsafe.Pointer(&osInfo)))
|
||||
if ret != 0 {
|
||||
return
|
||||
}
|
||||
|
||||
// Platform
|
||||
platform = strings.Trim(osInfo.Caption, " ")
|
||||
k, err := registry.OpenKey(registry.LOCAL_MACHINE, `SOFTWARE\Microsoft\Windows NT\CurrentVersion`, registry.QUERY_VALUE)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
defer k.Close()
|
||||
platform, _, err = k.GetStringValue("ProductName")
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if !strings.HasPrefix(platform, "Microsoft") {
|
||||
platform = "Microsoft " + platform
|
||||
}
|
||||
csd, _, err := k.GetStringValue("CSDVersion")
|
||||
if err == nil {
|
||||
platform += " " + csd
|
||||
}
|
||||
|
||||
// PlatformFamily
|
||||
switch osInfo.ProductType {
|
||||
switch osInfo.wProductType {
|
||||
case 1:
|
||||
family = "Standalone Workstation"
|
||||
case 2:
|
||||
@ -200,7 +208,7 @@ func PlatformInformationWithContext(ctx context.Context) (platform string, famil
|
||||
}
|
||||
|
||||
// Platform Version
|
||||
version = fmt.Sprintf("%s Build %s", osInfo.Version, osInfo.BuildNumber)
|
||||
version = fmt.Sprintf("%d.%d.%d Build %d", osInfo.dwMajorVersion, osInfo.dwMinorVersion, osInfo.dwBuildNumber, osInfo.dwBuildNumber)
|
||||
|
||||
return
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user