[英]Shutting down windows using golang code
I am making a program that automates some tedious tasks for me, after the program is done I want to shutdown windows. 我正在制作一个程序,为我自动完成一些繁琐的任务,程序完成后我想关闭windows。 I know this can be done in for example C#
我知道这可以在例如C#中完成
How can I shutdown window using golang? 如何使用golang关闭窗口?
There is no "Shutdown OS" function in the syscall
package, because there is no common interface provided for that by all operating systems. syscall
包中没有“关闭OS”功能,因为所有操作系统都没有提供通用接口。
Note: there is a syscall.Shutdown()
function, but that is to shutdown a socket , and not to shutdown the operating system. 注意:有一个
syscall.Shutdown()
函数,但这是关闭套接字 ,而不是关闭操作系统。
The easiest would be to just execute the shutdown
command using the os/exec
package, eg 最简单的方法是使用
os/exec
包执行shutdown
命令,例如
if err := exec.Command("cmd", "/C", "shutdown", "/s").Run(); err != nil {
fmt.Println("Failed to initiate shutdown:", err)
}
The above command initiates a shutdown sequence which usually takes 1 minute to really shut down the system (and there's room to abort it with shutdown /a
). 上面的命令启动一个关闭序列,通常需要1分钟来真正关闭系统(并且有空间可以通过
shutdown /a
中止它)。 You may provide different arguments to the shutdown
command to not wait 1 minute but proceed immediately: shutdown /t 0 /s
(execute shutdown /?
to get a list of all options). 您可以为
shutdown
命令提供不同的参数,使其不等待1分钟,但立即继续: shutdown /t 0 /s
(执行shutdown /?
以获取所有选项的列表)。
There is also a Windows API call to shutdown the system: ExitWindowsEx()
. 还有一个Windows API调用来关闭系统:
ExitWindowsEx()
。 It has 2 parameters, first is the flags to define the shutdown type ( 0x08
means Shuts down the system and turns off the power.
), second is to provide a reason for the shutdown. 它有2个参数,第一个是定义关闭类型的标志(
0x08
表示Shuts down the system and turns off the power.
),第二个是提供关闭的原因。 To call this from Go, you can do that like this: 要从Go调用它,你可以这样做:
user32 := syscall.MustLoadDLL("user32")
defer user32.Release()
exitwin := user32.MustFindProc("ExitWindowsEx")
r1, _, err := exitwin.Call(0x08, 0)
if r1 != 1 {
fmt.Println("Failed to initiate shutdown:", err)
}
But know that you need SE_SHUTDOWN_NAME
privilege to call ExitWindowsEx()
, else you get an error message like: 但是知道你需要
SE_SHUTDOWN_NAME
权限才能调用ExitWindowsEx()
,否则你会收到如下错误消息:
Failed to initiate shutdown: A required privilege is not held by the client.
See this example how to acquire the required privilege . 请参阅此示例, 了解如何获取所需的权限 。
Thanks for the post, very helpful. 谢谢你的帖子,非常有帮助。 here is a complete function that performs a reboot.
这是一个执行重启的完整功能。 It follows exactly the Microsoft example as noted before.
它完全遵循前面提到的Microsoft示例。 should help saving time in figuring out the structs:
应该有助于节省时间来确定结构:
import (
"fmt"
"syscall"
"unsafe"
)
// error is nil on success
func reboot() error {
user32 := syscall.MustLoadDLL("user32")
defer user32.Release()
kernel32 := syscall.MustLoadDLL("kernel32")
defer user32.Release()
advapi32 := syscall.MustLoadDLL("advapi32")
defer advapi32.Release()
ExitWindowsEx := user32.MustFindProc("ExitWindowsEx")
GetCurrentProcess := kernel32.MustFindProc("GetCurrentProcess")
GetLastError := kernel32.MustFindProc("GetLastError")
OpenProdcessToken := advapi32.MustFindProc("OpenProcessToken")
LookupPrivilegeValue := advapi32.MustFindProc("LookupPrivilegeValueW")
AdjustTokenPrivileges := advapi32.MustFindProc("AdjustTokenPrivileges")
currentProcess, _, _ := GetCurrentProcess.Call()
const tokenAdjustPrivileges = 0x0020
const tokenQuery = 0x0008
var hToken uintptr
result, _, err := OpenProdcessToken.Call(currentProcess, tokenAdjustPrivileges|tokenQuery, uintptr(unsafe.Pointer(&hToken)))
if result != 1 {
fmt.Println("OpenProcessToken(): ", result, " err: ", err)
return err
}
//fmt.Println("hToken: ", hToken)
const SeShutdownName = "SeShutdownPrivilege"
type Luid struct {
lowPart uint32 // DWORD
highPart int32 // long
}
type LuidAndAttributes struct {
luid Luid // LUID
attributes uint32 // DWORD
}
type TokenPrivileges struct {
privilegeCount uint32 // DWORD
privileges [1]LuidAndAttributes
}
var tkp TokenPrivileges
result, _, err = LookupPrivilegeValue.Call(uintptr(0), uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(SeShutdownName))), uintptr(unsafe.Pointer(&(tkp.privileges[0].luid))))
if result != 1 {
fmt.Println("LookupPrivilegeValue(): ", result, " err: ", err)
return err
}
//fmt.Println("LookupPrivilegeValue luid: ", tkp.privileges[0].luid)
const SePrivilegeEnabled uint32 = 0x00000002
tkp.privilegeCount = 1
tkp.privileges[0].attributes = SePrivilegeEnabled
result, _, err = AdjustTokenPrivileges.Call(hToken, 0, uintptr(unsafe.Pointer(&tkp)), 0, uintptr(0), 0)
if result != 1 {
fmt.Println("AdjustTokenPrivileges() ", result, " err: ", err)
return err
}
result, _, _ = GetLastError.Call()
if result != 0 {
fmt.Println("GetLastError() ", result)
return err
}
const ewxForceIfHung = 0x00000010
const ewxReboot = 0x00000002
const shutdownReasonMajorSoftware = 0x00030000
result, _, err = ExitWindowsEx.Call(ewxReboot|ewxForceIfHung, shutdownReasonMajorSoftware)
if result != 1 {
fmt.Println("Failed to initiate reboot:", err)
return err
}
return nil
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.