How to ask for administer privileges on Windows with Go

This is the technique that I use to detect if I am running as administrator, and if not relaunch myself with a UAC prompt. This allows me to run as a standard user in most cases, and only elevate when needed. I use this in command line tools where most functions don't need admin rights, but functions like -install or -uninstall do since they're writing to HKLM in the registry or Program Files. No manifest is necessary with this method.

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
}

More details available here:
https://gist.github.com/jerblack/d0eb182cc5a1c1d92d92a4c4fcc416c6


You need to embed a manifest file which will tell Windows that you want elevated privileges.

The example from that page is:

<?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>

This go-nuts post suggests that using rsrc should do the trick for you.

Tags:

Windows

Go