使用Golang获取Windows空闲时间(GetLastInputInfo或类似)

问题描述 投票:0回答:3

有没有使用Go获取Windows系统空闲时间的示例或方法?
我一直在查看 Golang 站点上的文档,但我认为我缺少如何访问(和使用)API 来获取包括空闲时间在内的系统信息。

winapi go idle-timer
3个回答
26
投票

Go 的网站经过硬编码以显示 Linux 上标准库包的文档。您需要获取 godoc 并自己运行它:

go get golang.org/x/tools/cmd/godoc
godoc --http=:6060

然后在网络浏览器中打开

http://127.0.0.1:6060/

值得注意的是包

syscall
,它提供了访问 DLL 中函数的工具,包括 UTF-16 帮助程序和回调生成函数。

对 Go 树进行快速递归搜索表明它没有特别针对

GetLastInputInfo()
的 API,因此除非我遗漏了某些内容,否则您应该能够直接从 DLL 调用该函数:

user32 := syscall.MustLoadDLL("user32.dll") // or NewLazyDLL() to defer loading
getLastInputInfo := user32.MustFindProc("GetLastInputInfo") // or NewProc() if you used NewLazyDLL()
// or you can handle the errors in the above if you want to provide some alternative
r1, _, err := getLastInputInfo.Call(uintptr(arg))
// err will always be non-nil; you need to check r1 (the return value)
if r1 == 0 { // in this case
    panic("error getting last input info: " + err.Error())
}

您的案例涉及一个结构。据我所知,您可以重新创建平面结构(保持字段顺序相同),但是您必须将原始中的任何

int
字段转换为
int32
,否则事情会在64位上崩溃Windows。请参阅 MSDN 上的Windows 数据类型页面,了解相应的等效类型。在你的情况下,这将是

var lastInputInfo struct {
    cbSize uint32
    dwTime uint32
}

因为这个(就像 Windows API 中的许多结构体一样)有一个

cbSize
字段,要求您使用结构体的大小来初始化它,所以我们也必须这样做:

lastInputInfo.cbSize = uint32(unsafe.Sizeof(lastInputInfo))

现在我们只需要将指向该

lastInputInfo
变量的指针传递给函数即可:

r1, _, err := getLastInputInfo.Call(
    uintptr(unsafe.Pointer(&lastInputInfo)))

并且记住导入

syscall
unsafe

DLL/LazyDLL.Call()
的所有参数都是
uintptr
r1
返回也是如此。 Windows 上永远不会使用
_
返回(它与使用的 ABI 有关)。


由于我已经介绍了在 Go 中使用 Windows API 所需了解的大部分内容,而这些内容是无法从阅读

syscall
文档中收集到的,所以我还会说(这与上述问题无关)如果函数有 ANSI 和 Unicode 版本,您应该使用 Unicode 版本(
W
后缀)和
syscall
包中的 UTF-16 转换函数以获得最佳结果。

我认为这就是您(或任何人)在 Go 程序中使用 Windows API 所需的全部信息。


3
投票

关于andlabs的回答。这是准备使用的示例:

import (
    "time"
    "unsafe"
    "syscall"
    "fmt"
)

var (
    user32            = syscall.MustLoadDLL("user32.dll")
    kernel32          = syscall.MustLoadDLL("kernel32.dll")
    getLastInputInfo  = user32.MustFindProc("GetLastInputInfo")
    getTickCount      = kernel32.MustFindProc("GetTickCount")
    lastInputInfo struct {
        cbSize uint32
        dwTime uint32
    }
)

func IdleTime() time.Duration {
    lastInputInfo.cbSize = uint32(unsafe.Sizeof(lastInputInfo))
    currentTickCount, _, _ := getTickCount.Call()
    r1, _, err := getLastInputInfo.Call(uintptr(unsafe.Pointer(&lastInputInfo)))
    if r1 == 0 {
            panic("error getting last input info: " + err.Error())
    }
    return time.Duration((uint32(currentTickCount) - lastInputInfo.dwTime)) * time.Millisecond
}

func main() {
    t := time.NewTicker(1 * time.Second)
    for range t.C {
        fmt.Println(IdleTime())
    }
}

这是每秒代码打印空闲时间。尝试运行并且不要触摸鼠标/键盘


0
投票

如果您愿意使用现有的包而不是实现自己的包,请参阅 lextoumbourou 的以下存储库:

https://github.com/lextoumbourou/idle

使用示例:

package main

import (
    "fmt"

    "github.com/lextoumbourou/idle"
)

func main() {
    idleTime, _ := idle.Get()
    fmt.Println(idleTime)
}

打印当前用户的空闲时间

© www.soinside.com 2019 - 2024. All rights reserved.