簡體   English   中英

使用golang代碼關閉窗口

[英]Shutting down windows using golang code

我正在制作一個程序,為我自動完成一些繁瑣的任務,程序完成后我想關閉windows。 我知道這可以在例如C#中完成

如何使用golang關閉窗口?

syscall包中沒有“關閉OS”功能,因為所有操作系統都沒有提供通用接口。

注意:有一個syscall.Shutdown()函數,但這是關閉套接字 ,而不是關閉操作系統。

最簡單的方法是使用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() 它有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.

請參閱此示例, 了解如何獲取所需的權限

謝謝你的帖子,非常有幫助。 這是一個執行重啟的完整功能。 它完全遵循前面提到的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
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM