dsafyx8454
2016-09-20 13:19
浏览 269
已采纳

使用golang代码关闭窗口

I am making a program that automates some tedious tasks for me, after the program is done I want to shutdown windows. I know this can be done in for example C#

How can I shutdown window using golang?

图片转代码服务由CSDN问答提供 功能建议

我正在为我制作一个可以自动完成一些乏味任务的程序,在完成该程序后,我想关闭Windows。 我知道可以在例如C#

中完成此操作,如何使用golang关闭窗口?

  • 写回答
  • 关注问题
  • 收藏
  • 邀请回答

2条回答 默认 最新

  • douyi3307 2016-09-20 15:40
    已采纳

    There is no "Shutdown OS" function in the syscall package, because there is no common interface provided for that by all operating systems.

    Note: there is a syscall.Shutdown() function, but that is to shutdown a socket, and not to shutdown the operating system.

    The easiest would be to just execute the shutdown command using the os/exec package, e.g.

    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). 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).

    There is also a Windows API call to shutdown the system: 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. To call this from Go, you can do that like this:

    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:

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

    See this example how to acquire the required privilege.

    已采纳该答案
    打赏 评论
  • douyi3760 2019-03-22 17:19

    Thanks for the post, very helpful. here is a complete function that performs a reboot. It follows exactly the Microsoft example as noted before. 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
    }
    
    打赏 评论

相关推荐 更多相似问题