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