Skip to content

Commit 2bc794f

Browse files
committed
Transformed into library
1 parent cdad3d5 commit 2bc794f

File tree

1 file changed

+37
-49
lines changed

1 file changed

+37
-49
lines changed

runas.go

Lines changed: 37 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -101,66 +101,54 @@ func shellExecuteError(code windows.Handle) error {
101101
}
102102
}
103103

104-
func installDrivers() error {
105-
if !IsAdmin() {
106-
// if not elevated, relaunch by shellexecute with runas verb set
107-
var runas, execFile, currDir, args *uint16
108-
var err error
104+
// RunElevated starts the given process with elevated priviledges.
105+
// An UAC prompt is displayed to the user to confirm the action.
106+
func RunElevated(executable, workingDir string, args []string, awaitProcCompletion bool) (int, error) {
107+
var verb, file, directory, parameters *uint16
108+
var err error
109109

110-
if runas, err = windows.UTF16PtrFromString("runas"); err != nil {
111-
return err
112-
}
113-
if exe, err := os.Executable(); err != nil {
114-
return err
115-
} else if execFile, err = windows.UTF16PtrFromString(exe); err != nil {
116-
return err
117-
}
118-
if cwd, err := os.Getwd(); err != nil {
119-
return err
120-
} else if currDir, err = windows.UTF16PtrFromString(cwd); err != nil {
121-
return err
122-
}
123-
if args, err = windows.UTF16PtrFromString(strings.Join(os.Args[1:], " ")); err != nil {
124-
return err
125-
}
110+
if verb, err = windows.UTF16PtrFromString("runas"); err != nil {
111+
return 0, err
112+
}
113+
if file, err = windows.UTF16PtrFromString(executable); err != nil {
114+
return 0, err
115+
}
116+
if directory, err = windows.UTF16PtrFromString(workingDir); err != nil {
117+
return 0, err
118+
}
119+
if parameters, err = windows.UTF16PtrFromString(strings.Join(os.Args[1:], " ")); err != nil {
120+
return 0, err
121+
}
126122

127-
execInfo := &shellExecuteInfo{
128-
size: uint32(unsafe.Sizeof(shellExecuteInfo{})),
129-
verb: runas,
130-
directory: currDir,
131-
file: execFile,
132-
parameters: args,
133-
show: windows.SW_SHOW, //HIDE,
134-
mask: SEE_MASK_NOCLOSEPROCESS,
135-
}
136-
if !shellExecuteEx(execInfo) {
137-
return shellExecuteError(execInfo.instApp)
138-
}
123+
execInfo := &shellExecuteInfo{
124+
size: uint32(unsafe.Sizeof(shellExecuteInfo{})),
125+
verb: verb,
126+
directory: directory,
127+
file: file,
128+
parameters: parameters,
129+
show: windows.SW_SHOW, //HIDE,
130+
mask: SEE_MASK_NOCLOSEPROCESS,
131+
}
132+
if !shellExecuteEx(execInfo) {
133+
return 0, shellExecuteError(execInfo.instApp)
134+
}
139135

140-
// Wait for process completion
136+
if awaitProcCompletion {
141137
const STILL_ACTIVE = 259 // https://learn.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-getexitcodeprocess#remarks
142138
var exitCode uint32 = STILL_ACTIVE
143139
for exitCode == STILL_ACTIVE {
144140
time.Sleep(250 * time.Millisecond)
145141
if err := windows.GetExitCodeProcess(execInfo.process, &exitCode); err != nil {
146-
return fmt.Errorf("waiting for process exit: %w", err)
142+
return 0, fmt.Errorf("waiting for process exit: %w", err)
147143
}
148144
}
149-
if exitCode != 0 {
150-
return fmt.Errorf("process terminated with exitcode %d", exitCode)
151-
}
152-
return nil
145+
return int(exitCode), nil
153146
}
154-
155-
fmt.Println("started")
156-
time.Sleep(4 * time.Second)
157-
fmt.Println("completed!")
158-
time.Sleep(time.Second)
159-
return nil
147+
return 0, nil
160148
}
161149

162-
func IsAdmin() bool {
163-
elevated := windows.GetCurrentProcessToken().IsElevated()
164-
fmt.Printf("admin %v\n", elevated)
165-
return elevated
150+
// IsAdminProcess returns true if the current process already
151+
// runs as admin.
152+
func IsAdminProcess() bool {
153+
return windows.GetCurrentProcessToken().IsElevated()
166154
}

0 commit comments

Comments
 (0)