使用 golang 代码关闭 windows
Shutting down windows using golang code
我正在制作一个程序,为我自动执行一些繁琐的任务,程序完成后我想关闭 windows。我知道这可以在例如 C#
中完成
如何使用 golang 关闭 window?
syscall
包中没有 "Shutdown OS" 函数,因为所有操作系统都没有为此提供通用接口。
注:有一个syscall.Shutdown()
function, but that is to shutdown a socket,并没有关闭操作系统。
最简单的方法是只执行 shutdown
command using the os/exec
包,例如
if err := exec.Command("cmd", "/C", "shutdown", "/s").Run(); err != nil {
fmt.Println("Failed to initiate shutdown:", err)
}
上面的命令启动一个关机序列,通常需要 1 分钟才能真正关闭系统(并且有足够的空间用 shutdown /a
中止它)。您可以为 shutdown
命令提供不同的参数以不等待 1 分钟而是立即继续:shutdown /t 0 /s
(执行 shutdown /?
以获取所有选项的列表)。
还有一个WindowsAPI关闭系统的调用:ExitWindowsEx()
。它有 2 个参数,第一个是定义关闭类型的标志(0x08
表示 Shuts down the system and turns off the power.
),第二个是提供关闭的原因。要从 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)
}
但要知道您需要 SE_SHUTDOWN_NAME
权限才能调用 ExitWindowsEx()
,否则您会收到如下错误消息:
Failed to initiate shutdown: A required privilege is not held by the client.
感谢 post,非常有帮助。
这是执行重启的完整函数。它完全遵循前面提到的 Microsoft 示例。应该有助于节省计算结构的时间:
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
}
我正在制作一个程序,为我自动执行一些繁琐的任务,程序完成后我想关闭 windows。我知道这可以在例如 C#
中完成如何使用 golang 关闭 window?
syscall
包中没有 "Shutdown OS" 函数,因为所有操作系统都没有为此提供通用接口。
注:有一个syscall.Shutdown()
function, but that is to shutdown a socket,并没有关闭操作系统。
最简单的方法是只执行 shutdown
command using the os/exec
包,例如
if err := exec.Command("cmd", "/C", "shutdown", "/s").Run(); err != nil {
fmt.Println("Failed to initiate shutdown:", err)
}
上面的命令启动一个关机序列,通常需要 1 分钟才能真正关闭系统(并且有足够的空间用 shutdown /a
中止它)。您可以为 shutdown
命令提供不同的参数以不等待 1 分钟而是立即继续:shutdown /t 0 /s
(执行 shutdown /?
以获取所有选项的列表)。
还有一个WindowsAPI关闭系统的调用:ExitWindowsEx()
。它有 2 个参数,第一个是定义关闭类型的标志(0x08
表示 Shuts down the system and turns off the power.
),第二个是提供关闭的原因。要从 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)
}
但要知道您需要 SE_SHUTDOWN_NAME
权限才能调用 ExitWindowsEx()
,否则您会收到如下错误消息:
Failed to initiate shutdown: A required privilege is not held by the client.
感谢 post,非常有帮助。 这是执行重启的完整函数。它完全遵循前面提到的 Microsoft 示例。应该有助于节省计算结构的时间:
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
}