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

时间:2014-04-08 22:29:44

标签: winapi go idle-timer

是否有使用Go获取Windows系统空闲时间的示例或方法?
 我一直在看Golang网站上的文档,但我想我错过了如何访问(和使用)API以获取系统信息,包括空闲时间。

2 个答案:

答案 0 :(得分:24)

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)))

并且只记得导入syscallunsafe

DLL/LazyDLL.Call()的所有参数均为uintptrr1返回。 _返回从未在Windows上使用(它与使用的ABI有关)。


由于我通过阅读syscall文档而无法收集的Go中使用Windows API的大部分内容,我也会说(这与上述问题无关) )如果函数同时具有ANSI和Unicode版本,则应使用Unicode版本(W后缀)和包syscall中的UTF-16转换函数以获得最佳结果。

我认为,您(或任何人)的所有信息都需要在Go程序中使用Windows API。

答案 1 :(得分:1)

关于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())
    }
}

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