【发布时间】:2014-04-08 22:29:43
【问题描述】:
有没有使用 Go 获取 Windows 系统空闲时间的示例或方法?
我一直在查看 Golang 站点上的文档,但我想我错过了如何访问(和使用)API 来获取系统信息,包括空闲时间。
【问题讨论】:
标签: winapi go idle-timer
有没有使用 Go 获取 Windows 系统空闲时间的示例或方法?
我一直在查看 Golang 站点上的文档,但我想我错过了如何访问(和使用)API 来获取系统信息,包括空闲时间。
【问题讨论】:
标签: winapi go idle-timer
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,否则 things will break on 64-bit Windows .请咨询Windows Data Types page on MSDN 以获取相应的等效类型。在你的情况下,这将是
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 返回也是如此。 _ return 在 Windows 上从不使用(它与使用的 ABI 有关)。
由于我回顾了在 Go 中使用 Windows API 所需了解的大部分内容,而这些内容是通过阅读 syscall 文档无法收集到的,我还要说(这与上述问题无关)如果函数同时具有 ANSI 和 Unicode 版本,则应使用 Unicode 版本(W 后缀)和包 syscall 中的 UTF-16 转换函数以获得最佳效果。
我认为这就是您(或任何人)在 Go 程序中使用 Windows API 所需的所有信息。
【讨论】:
GetLastInputInfo()的返回值,according to MSDN代表函数是否成功。您需要检查 r1,如果非零,则在调用后将 dwTime 从您的结构中取出,这是您真正想要的值。 (另见_Out_注解,它表示函数在那里返回值。)如果r1 == 0,err将包含错误信息(即为你调用GetLastError())。
关于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())
}
}
这是每秒的代码打印空闲时间。尝试运行,不要触摸鼠标/键盘
【讨论】: