使用windows自带的当系统空闲一段时间后进入睡眠模式不太可靠,用golang写了个小工具定时使用getLastInputInfo获取上次鼠标和键盘的活动时间,超过一段时间未操作进入睡眠状态,当在全屏状态时不进入睡眠状态,如在播放视频时,全屏排除锁屏界面和win+d快捷键进入的桌面。
获取是否有程序在全屏使用的golang cgo实现,windows下编译运行需安装gcc,可安装TDM-GCC。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 | package main /* #include <windows.h> #include <stdio.h> int CheckFullscreen() { int bFullScreen = 0; HWND hWnd = GetForegroundWindow(); RECT rcApp, rcDesk; GetWindowRect(GetDesktopWindow(), &rcDesk); if (hWnd!=GetDesktopWindow() && hWnd!=GetShellWindow()) { GetWindowRect(hWnd, &rcApp); if (rcApp.left<=rcDesk.left && rcApp.top<=rcDesk.top && rcApp.right>=rcDesk.right && rcApp.bottom>=rcDesk.bottom) { char wnd_name[256]; char wnd_title[256]; GetWindowText(hWnd,wnd_title,sizeof(wnd_title)); GetClassName(hWnd, wnd_name, sizeof(wnd_name)); printf("title: %s\n", wnd_title); printf("name: %s\n", wnd_name); if (strcmp(wnd_name, "Windows.UI.Core.CoreWindow") != 0 && strcmp(wnd_name, "WorkerW") != 0){ bFullScreen =1; } } } return bFullScreen; } */ import "C" import ( "flag" "fmt" "os/exec" "strings" "syscall" "time" "unsafe" ) 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() uint32 { lastInputInfo.cbSize = uint32 (unsafe.Sizeof(lastInputInfo)) currentTickCount, _, _ := getTickCount.Call() r1, _, err := getLastInputInfo.Call( uintptr (unsafe.Pointer(&lastInputInfo))) if r1 == 0 { fmt.Println( "error getting last input info: " + err.Error()) return 0 } return ( uint32 (currentTickCount) - lastInputInfo.dwTime) } func Execute(command string ) ( bool , string , error ) { // splitting head => g++ parts => rest of the command parts := strings.Fields(command) head := parts[0] parts = parts[1: len (parts)] out, err := exec.Command(head, parts...).Output() if err != nil { return false , "" , err } return true , string (out), nil } func sleepCommandLineImplementation(cmd string ) { if cmd == "" { cmd = "C:\\Windows\\System32\\rundll32.exe powrprof.dll,SetSuspendState 0,1,0" } fmt.Println( "Sleep implementation [windows], sleep command is [" , cmd, "]" ) _, _, err := Execute(cmd) if err != nil { fmt.Println( "Can't execute command [" + cmd + "] : " + err.Error()) } else { fmt.Println( "Command correctly executed" ) } } func sleepDLLImplementation() { var mod = syscall.NewLazyDLL( "Powrprof.dll" ) var proc = mod.NewProc( "SetSuspendState" ) // DLL API : public static extern bool SetSuspendState(bool hiberate, bool forceCritical, bool disableWakeEvent); // ex. : uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr("Done Title"))), ret, _, _ := proc.Call(0, uintptr (0), // hibernate uintptr (1), // forceCritical uintptr (0)) // disableWakeEvent fmt.Println( "Command executed, result code [" + fmt.Sprint(ret) + "]" ) } func main() { var timeout,interval int var execute string flag.IntVar(&timeout, "t" , 15, "minute" ) flag.IntVar(&interval, "i" , 60, "second" ) flag.StringVar(&execute, "c" , "api" , "api or cli" ) flag.Parse() fmt.Println( "timeout" , timeout, "minute" ) fmt.Println( "interval" , interval, "second" ) fmt.Println( "execute" , execute) //间隔不能太小,不然通过网络唤醒间隔时间内无操作会再次进入睡眠 t := time.NewTicker(time.Duration(interval) * time.Second) for range t.C { idle := IdleTime() fmt.Println(time.Now().Format( "2006-01-02 15:04:05" ) , "idle time" , idle) fmt.Println(time.Now().Format( "2006-01-02 15:04:05" ) , "full screen" , C.CheckFullscreen()) if idle > uint32 (timeout)*60*1000 && C.CheckFullscreen() != 1 { if execute == "api" { sleepDLLImplementation() } else { sleepCommandLineImplementation( "rundll32.exe powrprof.dll,SetSuspendState 0,1,0" ) //sleepCommandLineImplementation("") } } } } |
如进入睡眠时为休眠,可关闭休眠:
1 | powercfg -h off |
参考:
https://bbs.csdn.net/topics/390838652
https://stackoverflow.com/questions/22949444/using-golang-to-get-windows-idle-time-getlastinputinfo-or-similar
https://github.com/SR-G/sleep-on-lan
https://www.cnblogs.com/yeshou/p/5197765.html
标签:none