【问题标题】:Shutting down windows using golang code使用 golang 代码关闭窗口
【发布时间】:2016-09-20 13:19:09
【问题描述】:

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

如何使用 golang 关闭窗口?

【问题讨论】:

标签: windows go shutdown


【解决方案1】:

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

注意:有一个syscall.Shutdown()的功能,不过是给shutdown a socket,而不是关闭操作系统。

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

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 调用:ExitWindowsEx()。它有两个参数,第一个是定义关闭类型的标志(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.

请参阅此示例how to acquire the required privilege

【讨论】:

    【解决方案2】:

    感谢您的帖子,非常有帮助。 这是一个执行重启的完整功能。它完全遵循前面提到的 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
    }
    

    【讨论】:

      猜你喜欢
      • 2015-07-02
      • 1970-01-01
      • 1970-01-01
      • 2014-06-16
      • 2023-04-04
      • 2012-12-03
      • 2016-12-24
      • 2021-03-27
      • 1970-01-01
      相关资源
      最近更新 更多