使用golang代码关闭windows

使用golang代码关闭windows,windows,go,shutdown,Windows,Go,Shutdown,我正在制作一个程序,为我自动化一些繁琐的任务,程序完成后,我想关闭windows。我知道这可以在示例C中完成# 如何使用golang关闭窗口?软件包中没有“关闭操作系统”功能,因为所有操作系统都没有为其提供通用接口 注意:有一个功能,但它是关闭操作系统,而不是关闭操作系统 最简单的方法是使用包执行命令,例如 if err := exec.Command("cmd", "/C", "shutdown", "/s").Run(); err != nil { fmt.Println("Fail

我正在制作一个程序,为我自动化一些繁琐的任务,程序完成后,我想关闭windows。我知道这可以在示例C中完成#

如何使用golang关闭窗口?

软件包中没有“关闭操作系统”功能,因为所有操作系统都没有为其提供通用接口

注意:有一个功能,但它是关闭操作系统,而不是关闭操作系统

最简单的方法是使用包执行命令,例如

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/?
以获取所有选项的列表)

还有一个Windows API调用用于关闭系统:。它有两个参数,第一个是定义关机类型的标志(
0x08
表示
关闭系统并关闭电源。
),第二个是提供关机原因。要从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\u SHUTDOWN\u NAME
权限才能调用
ExitWindowsEx()
,否则会收到如下错误消息:

Failed to initiate shutdown: A required privilege is not held by the client.

看看这个例子。

谢谢你的帖子,非常有用。 下面是执行重新启动的完整函数。它完全遵循前面提到的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
}
?@u_mulder我不这么认为。是到,而不是操作系统。