有没有关于使用Go获取Windows系统空闲时间的示例或方法?我一直在查看Golang网站上的文档,但我认为我不知道如何访问(和使用)API来获取包括空闲时间在内的系统信息。
Go语言的官网是默认展示Linux标准库文档的,而你需要获取godoc并自行运行:
go get golang.org/x/tools/cmd/godoc
godoc --http=:6060
然后在您的Web浏览器中打开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
}
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 所需的所有信息。关于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())
}
}
这是打印空闲时间的代码,每秒钟打印一次。尝试运行并不要触摸鼠标/键盘。
https://github.com/lextoumbourou/idle
用法示例:
package main
import (
"fmt"
"github.com/lextoumbourou/idle"
)
func main() {
idleTime, _ := idle.Get()
fmt.Println(idleTime)
}
GetLastInputInfo()
返回的返回值,根据MSDN的说明,它表示函数是否成功。您需要检查r1,如果非零,则在调用后从结构中获取dwTime
,这是您实际想要的值。(请参见_Out_
注释,该注释指示函数在那里返回值。)如果r1 == 0,则err将包含错误信息(即为您调用了GetLastError()
)。 - andlabs