如何使用Go在Windows上请求管理员权限

时间:2015-07-22 08:38:55

标签: windows go

我想要为我的应用程序实现的目标是需要右键单击并选择以管理员身份运行每次我想运行它。我希望Windows提示我获得管理员权限,就像使用其他Windows应用程序一样。

考虑以下代码:

package main

import (
    "fmt"
    "io/ioutil"
    "time"
)

func main() {
    err := ioutil.WriteFile("C:/Windows/test.txt", []byte("TESTING!"), 0644)
    if err != nil {
        fmt.Println(err.Error())
        time.Sleep(time.Second * 3)
    }
}

如果您编译它并双击它将打印:

  

open:C:\ Windows \ test.txt:访问被拒绝。

但是,如果右键单击并以管理员身份运行,它将创建并写入文件。

如何通过双击来询问管理员权限?

2 个答案:

答案 0 :(得分:15)

您需要嵌入一个manifest file,它会告诉Windows您需要提升权限。

该页面的示例是:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
<assemblyIdentity
    version="9.0.0.0"
    processorArchitecture="x86"
    name="myapp.exe"
    type="win32"
/>
<description>My App</description>
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
    <security>
        <requestedPrivileges>
            <requestedExecutionLevel level="requireAdministrator" uiAccess="false"/>
        </requestedPrivileges>
    </security>
</trustInfo>
</assembly>

go-nuts post表示使用rsrc可以为您解决问题。

答案 1 :(得分:0)

这是我用来检测我是否以管理员身份运行以及是否未使用UAC提示符重新启动的技术。这使我在大多数情况下可以以标准用户身份运行,并且仅在需要时才进行升级。我在大多数功能不需要管理员权限的命令行工具中使用此命令,但-install或-uninstall之类的功能却需要,因为它们是在注册表或程序文件中写入HKLM的。使用此方法无需清单。

package main

import (
    "fmt"
    "golang.org/x/sys/windows"
    "os"
    "syscall"
    "time"
)

func main() {
    // if not elevated, relaunch by shellexecute with runas verb set
    if !amAdmin() {
        runMeElevated()
    }
    time.Sleep(10*time.Second)

}

func runMeElevated() {
    verb := "runas"
    exe, _ := os.Executable()
    cwd, _ := os.Getwd()
    args := strings.Join(os.Args[1:], " ")

    verbPtr, _ := syscall.UTF16PtrFromString(verb)
    exePtr, _ := syscall.UTF16PtrFromString(exe)
    cwdPtr, _ := syscall.UTF16PtrFromString(cwd)
    argPtr, _ := syscall.UTF16PtrFromString(args)

    var showCmd int32 = 1 //SW_NORMAL

    err := windows.ShellExecute(0, verbPtr, exePtr, argPtr, cwdPtr, showCmd)
    if err != nil {
        fmt.Println(err)
    }
}

func amAdmin() bool {
    _, err := os.Open("\\\\.\\PHYSICALDRIVE0")
    if err != nil {
        fmt.Println("admin no")
        return false
    }
    fmt.Println("admin yes")
    return true
}

更多详细信息请参见:
https://gist.github.com/jerblack/d0eb182cc5a1c1d92d92a4c4fcc416c6