RunAsTask() - Auto-elevates script without UAC prompt

Post your working scripts, libraries and tools for AHK v1.1 and older
User avatar
SKAN
Posts: 1551
Joined: 29 Sep 2013, 16:58

RunAsTask() - Auto-elevates script without UAC prompt

21 Aug 2014, 18:01

V2 version is here RunAsTask() (25-Jul-2023)
 

Code: Select all

/*
 _      _    _               __ __      _      _                      _         _                        
| |__  | |_ | |_  _ __  _   / // /__ _ | |__  | | __ ___   ___  _ __ (_) _ __  | |_     ___   _ __  __ _ 
| '_ \ | __|| __|| '_ \(_) / // // _` || '_ \ | |/ // __| / __|| '__|| || '_ \ | __|   / _ \ | '__|/ _` |
| | | || |_ | |_ | |_) |_ / // /| (_| || | | ||   < \__ \| (__ | |   | || |_) || |_  _| (_) || |  | (_| |
|_| |_| \__| \__|| .__/(_)_//_/  \__,_||_| |_||_|\_\|___/ \___||_|   |_|| .__/  \__|(_)\___/ |_|   \__, |
                 |_|                                                    |_|                        |___/ 
RunAsTask() - Auto-elevates script without UAC prompt |  http://ahkscript.org/boards/viewtopic.php?t=4334        
_________________________________________________________________________________________________________
*/
 
RunAsTask() {                         ;  By SKAN,  http://goo.gl/yG6A1F,  CD:19/Aug/2014 | MD:22/Jul/2023

  Local CmdLine, TaskName, TaskExists, XML, TaskSchd, TaskRoot, RunAsTask
  Local TASK_CREATE := 0x2,  TASK_LOGON_INTERACTIVE_TOKEN := 3 

  Try TaskSchd  := ComObjCreate( "Schedule.Service" ),    TaskSchd.Connect()
    , TaskRoot  := TaskSchd.GetFolder( "\" )
  Catch
      Return "", ErrorLevel := 1    
  
  CmdLine       := ( A_IsCompiled ? "" : """"  A_AhkPath " """ ) . ( """" A_ScriptFullpath """"  )
  TaskName      := "[RunAsTask] " A_ScriptName " @" SubStr( "000000000"  DllCall( "NTDLL\RtlComputeCrc32"
                   , "Int",0, "WStr",CmdLine, "UInt",StrLen( CmdLine ) * 2, "UInt" ), -9 )

  Try RunAsTask := TaskRoot.GetTask( TaskName )
  TaskExists    := ! A_LastError 


  If ( not A_IsAdmin and TaskExists )      { 

    RunAsTask.Run( "" )
    ExitApp

  }

  If ( not A_IsAdmin and not TaskExists )  { 

    Run *RunAs %CmdLine%, %A_ScriptDir%, UseErrorLevel
    ExitApp

  }

  If ( A_IsAdmin and not TaskExists )      {  

    XML := "
    ( LTrim Join
      <?xml version=""1.0"" ?><Task xmlns=""http://schemas.microsoft.com/windows/2004/02/mit/task""><Regi
      strationInfo /><Triggers /><Principals><Principal id=""Author""><LogonType>InteractiveToken</LogonT
      ype><RunLevel>HighestAvailable</RunLevel></Principal></Principals><Settings><MultipleInstancesPolic
      y>Parallel</MultipleInstancesPolicy><DisallowStartIfOnBatteries>false</DisallowStartIfOnBatteries><
      StopIfGoingOnBatteries>false</StopIfGoingOnBatteries><AllowHardTerminate>false</AllowHardTerminate>
      <StartWhenAvailable>false</StartWhenAvailable><RunOnlyIfNetworkAvailable>false</RunOnlyIfNetworkAva
      ilable><IdleSettings><StopOnIdleEnd>true</StopOnIdleEnd><RestartOnIdle>false</RestartOnIdle></IdleS
      ettings><AllowStartOnDemand>true</AllowStartOnDemand><Enabled>true</Enabled><Hidden>false</Hidden><
      RunOnlyIfIdle>false</RunOnlyIfIdle><DisallowStartOnRemoteAppSession>false</DisallowStartOnRemoteApp
      Session><UseUnifiedSchedulingEngine>false</UseUnifiedSchedulingEngine><WakeToRun>false</WakeToRun><
      ExecutionTimeLimit>PT0S</ExecutionTimeLimit></Settings><Actions Context=""Author""><Exec>
      <Command>""" ( A_IsCompiled ? A_ScriptFullpath : A_AhkPath ) """</Command>
      <Arguments>" ( !A_IsCompiled ? """" A_ScriptFullpath  """" : "" )   "</Arguments>
      <WorkingDirectory>" A_ScriptDir "</WorkingDirectory></Exec></Actions></Task>
    )"    

    TaskRoot.RegisterTask( TaskName, XML, TASK_CREATE, "", "", TASK_LOGON_INTERACTIVE_TOKEN )

  }         

Return TaskName, ErrorLevel := 0
} ; _____________________________________________________________________________________________________

Usage example:

Code: Select all

#NoTrayIcon
RunAsTask() ; self elevate 
Run RegEdit.exe
RunAsTask() elevates the calling script by registering a scheduled task with highest privileges on the *first run of the script.
For subsequent runs, it will start a parallel elevated instance via Task scheduler and original instance will exit.

*UAC will prompt on the first run.

RunAsTask() generates a unique Taskname , for a given script as in following pattern:
"[RunAsTask]" . A_Space . A_ScriptName . A_Space . "@" . ( CRC32 hash of file paths, as decimal )
eg. [RunAsTask] My Admin Script.ahk @0123456789
For every change in A_ScriptFullpath ( compiled / uncompiled ) or A_AhkPath + A_ScriptFullpath ( uncompiled ), a new task will be registered. It is up to the user to clean and maintain the task scheduler.

Here is a task scheduler export of XML which was registered by RunAsTask(). The items in red are not in script. Items in blue are variable.
Task scheduler XML export
Edit1: 2014/Aug/22 13:25 UTC

RunAsTask_CreateShortcut()
RunAsTask_CreateShortcut() is a supplementary function for RunAsTask(). It will create a shortcut for the Taskname returned by RunAsTask()
Shortcut target example: C:\Windows\system32\schtasks.exe /run /tn "[RunAsTask] MyAdminScript.ahk @3264355656"

Code: Select all

RunAsTask_CreateShortcut( TaskName := "", Folder := "", ShcName := "" ) { ; by SKAN, http://goo.gl/yG6A1F
  Local LINK, Description

  IfEqual, TaskName,, Return 
  LINK := ( FileExist( Folder )  ? Folder : A_ScriptDir ) "\" ( ShcName ? ShcName : A_ScriptName ) ".lnk"
  FileGetShortcut, %LINK%,,,, Description
  If ( Description <> Taskname ) 
    FileCreateShortcut, schtasks.exe, %LINK%, %A_WorkingDir%,/run /tn "%TaskName%", %TaskName%,,,, 7
}
Usage example:

Code: Select all

TaskName := RunAsTask()
RunAsTask_CreateShortcut( TaskName ) ; Places a shortcut in Script folder
Parameter examples:

Code: Select all

RunAsTask_CreateShortcut( TaskName, A_Desktop ) ; Shortcut on desktop
RunAsTask_CreateShortcut( Taskname, A_Startup, "My Admin Script" ) ; Place in Startup. Force link name to avoid multiple startup entries.
My Scripts and Functions: V1  V2
User avatar
joedf
Posts: 8937
Joined: 29 Sep 2013, 17:08
Location: Canada
Contact:

Re: RunAsTask() - Auto-elevates script without UAC prompt

21 Aug 2014, 18:41

Ahhh you're using the "Schtasks with elevate privileges" trick thingy, I remember I used it once in a c# program I wrote, I was thinking of using for aspdm, but then I realized that "dynamic" arguments can not be given without creating the task anew (due to security concerns)... For me I think that's the only disadvantage, it can be worked around, but it would use a small "dirty" trick..

Anyway, Kudos for making a nice simple to use function! Another one for the book, SKAN! ;)
Image Image Image Image Image
Windows 10 x64 Professional, Intel i5-8500, NVIDIA GTX 1060 6GB, 2x16GB Kingston FURY Beast - DDR4 3200 MHz | [About Me] | [About the AHK Foundation] | [Courses on AutoHotkey]
[ASPDM - StdLib Distribution] | [Qonsole - Quake-like console emulator] | [LibCon - Autohotkey Console Library]
User avatar
Nextron
Posts: 1391
Joined: 01 Oct 2013, 08:23
Location: Netherlands OS: Win10 AHK: Unicode x32

Re: RunAsTask() - Auto-elevates script without UAC prompt

21 Aug 2014, 18:50

Setting up my main script to run as admin using task scheduler is something I usually only do once per computer. Now I don't have to do it at all :thumbup:, although I added static autorun:=RunAsTask() to the function to make it auto-initialize. After that, you can use this similar script that does the opposite, to run process as unelevated user.
Last edited by Nextron on 21 Aug 2014, 18:56, edited 2 times in total.
User avatar
SKAN
Posts: 1551
Joined: 29 Sep 2013, 16:58

RunAsTask_CreateShortcut()

22 Aug 2014, 09:32

Added function: RunAsTask_CreateShortcut()
User avatar
SKAN
Posts: 1551
Joined: 29 Sep 2013, 16:58

Re: RunAsTask() - Auto-elevates script without UAC prompt

22 Aug 2014, 09:33

Nextron wrote:run process as unelevated user.
Why not use Run_() or ShellRun() available in Installer.ahk ?

Everything search engine launches everything elevated ( except explorer ).
I have set ShellRun.ahk in Options > General > Context Menu > Open (Files) > Command as $exec("shellrun.ahk" "%1")

Code: Select all

#NoTrayIcon
Param = %1%
ShellRun( Param )
Return

#Include C:\Program Files\AutoHotkey\Installer.ahk ; My A_Ahkpath is different
User avatar
Nextron
Posts: 1391
Joined: 01 Oct 2013, 08:23
Location: Netherlands OS: Win10 AHK: Unicode x32

Re: RunAsTask_CreateShortcut()

22 Aug 2014, 13:12

SKAN wrote:Added function: RunAsTask_CreateShortcut()
That's freaky. I thought about a feature like this yesterday, but then I thought: "Yeah, like I ever kill the AutoHotkey.exe process :lol:"
SKAN wrote:Why not use Run_() or ShellRun() available in Installer.ahk ?
I've got three function in my main script, RunAsLimitedUser() (launch with restricted security token), shellrun() (launch from user shell object) and RunAsUser() (launch as scheduled task) (all from here). I mostly use RunAsLimitedUser() because it returns me a PID. I've encountered a couple situations where it doesn't work properly and I use shellrun(). I mentioned RunAsUser() for its similarity.
arcticir
Posts: 693
Joined: 17 Nov 2013, 11:32

Re: RunAsTask() - Auto-elevates script without UAC prompt

22 Aug 2014, 17:13

Get commandline

Code: Select all

Process, Exist 
CmdLine:=winmgmts("CommandLine","ProcessId",ErrorLevel)

winmgmts(v,w:="ProcessId",n:="CommandLine",d:="Win32_Process",m:="winmgmts:{impersonationLevel=impersonate}!\\.\root\cimv2"){
	s:=[]
	for i in ComObjGet(m).ExecQuery("Select * from " d  (w ? " Where " w "='" n "'" :""))
		s.Insert(i[v])
	return s.MaxIndex()?(s.MaxIndex()=1?s.1:s):""
	}
User avatar
joedf
Posts: 8937
Joined: 29 Sep 2013, 17:08
Location: Canada
Contact:

Re: RunAsTask() - Auto-elevates script without UAC prompt

22 Aug 2014, 17:54

@arcticir nice share, but I don't think that's related, or is it?
Image Image Image Image Image
Windows 10 x64 Professional, Intel i5-8500, NVIDIA GTX 1060 6GB, 2x16GB Kingston FURY Beast - DDR4 3200 MHz | [About Me] | [About the AHK Foundation] | [Courses on AutoHotkey]
[ASPDM - StdLib Distribution] | [Qonsole - Quake-like console emulator] | [LibCon - Autohotkey Console Library]
User avatar
SKAN
Posts: 1551
Joined: 29 Sep 2013, 16:58

Re: RunAsTask() - Auto-elevates script without UAC prompt

23 Aug 2014, 10:52

@arcticir: May I ask how winmgmts() is better than DllCall( "GetCommandLine","Str" ) ? :roll:
you wrote:CmdLine More accurate
I intentionally have it the way it is. If the script is Run from an another script with shortpath, then CRC32 hash will differ and RunAsTask() will register it as a new task. Also there is the Reload command ( also as tray menu item) which inserts a /restart in command line.
joedf wrote:but it would use a small "dirty" trick..
Can you explain?, please. :)
User avatar
joedf
Posts: 8937
Joined: 29 Sep 2013, 17:08
Location: Canada
Contact:

Re: RunAsTask() - Auto-elevates script without UAC prompt

23 Aug 2014, 12:13

Well, maybe there are other ways to do this, but the only thing that comes to mind right now, is to write a temporary file at a predefined location.. Say, a file like myprogram.arguments.txt in AppData and the task could launch "thing.exe /taskmode" or something close telling it to go read that file... It's not ultra dirty but a little bit ;)
Hey! Maybe this could be a feature... Haha :D

Regards
Image Image Image Image Image
Windows 10 x64 Professional, Intel i5-8500, NVIDIA GTX 1060 6GB, 2x16GB Kingston FURY Beast - DDR4 3200 MHz | [About Me] | [About the AHK Foundation] | [Courses on AutoHotkey]
[ASPDM - StdLib Distribution] | [Qonsole - Quake-like console emulator] | [LibCon - Autohotkey Console Library]
User avatar
SKAN
Posts: 1551
Joined: 29 Sep 2013, 16:58

LaunchAsAdmin

23 Aug 2014, 17:16

joedf wrote:task could launch "thing.exe /taskmode" or something close telling it to go read that file
I did not think of that. Nice, thanks :)

Here is an another way where I rely on OnExit. The template also supports Reload, but is not being used.
As for parsing CmdLine, I will post a function in a *separate topic.

Edit: *Args() - Returns command line parameters as array

Code: Select all

; Launch any app as Admin.  By SKAN,  http://goo.gl/yG6A1F 
; Usage: Pass any app along with its parameters to this script.

#Warn
#NoTrayIcon
#SingleInstance, Ignore
OnExit, OnExit

TaskName := ""                                    ; else #Warn complains.
TaskName := RunAsTask()                           ; This function will never return on the first run

FileRead, CmdLine, %A_Temp%\%A_ScriptName%.tmp 

If ( CmdLine = "" )                               ; Script/shortcut was launched with another admin app  
     CmdLine := DllCall( "GetCommandLine","Str" ) ; or with context menu item "Run as Administrator" !!!

Loop % ( A_IsCompiled ? 1 : 2 )      ; Excludes 'AutoHotkey exe' and 'Script path' from the command line 
  CmdLine := DllCall( "shlwapi\PathGetArgs", "Str",CmdLine, "Str" )

Run %CmdLine%,, UseErrorLevel

Return                                                                ; // end of auto-execute section //
  
OnExit:
  OnExit
  IfNotEqual, A_ExitReason, Reload, FileDelete, %A_Temp%\%A_ScriptName%.tmp
  IfEqual, TaskName,, FileAppend, % DllCall( "GetCommandLine","Str" ), %A_Temp%\%A_ScriptName%.tmp, UTF-8
  ExitApp
Return 
User avatar
joedf
Posts: 8937
Joined: 29 Sep 2013, 17:08
Location: Canada
Contact:

Re: RunAsTask() - Auto-elevates script without UAC prompt

23 Aug 2014, 18:37

Oh! Nice, very interesting, I'll have to try it when I return from my trip, thanks for sharing. :)

Edit: cool, Reading from argv pointer!
Image Image Image Image Image
Windows 10 x64 Professional, Intel i5-8500, NVIDIA GTX 1060 6GB, 2x16GB Kingston FURY Beast - DDR4 3200 MHz | [About Me] | [About the AHK Foundation] | [Courses on AutoHotkey]
[ASPDM - StdLib Distribution] | [Qonsole - Quake-like console emulator] | [LibCon - Autohotkey Console Library]
User avatar
evilC
Posts: 4822
Joined: 27 Feb 2014, 12:30

Re: RunAsTask() - Auto-elevates script without UAC prompt

29 Sep 2015, 05:13

I have successfully used this lib for scripts that run on various people's home PCs, but I now have a need to run this on a VM at work, and I cannot get it to function - it pops up the UAC dialog every time.
Sure, we could turn UAC off, but the use case is automated tests, and turning off UAC is not desirable on these test VMs. Any ideas what may be stopping it from working?
I have tried with just the regedit test script and no joy :(

FYI, I am trying to use it to allow remove machines within the VM environment to read the event log of the Exchange server.
User avatar
evilC
Posts: 4822
Joined: 27 Feb 2014, 12:30

Re: RunAsTask() - Auto-elevates script without UAC prompt

02 Nov 2015, 11:24

I replaced run_as_admin in my project with RunAsTask, and now I am getting many, many reports of the application no longer starting.
I have managed to replicate the issue on a VM - every EXE I compile with RunAsTask suffers from the same issues if run on a PC with UAC on:

On double-clicking of the compiled EXE, nothing happens. The script does not run, no UAC prompt appears.
The only way to get the script to run is to right-click the EXE and select "Run as Administrator". The UAC prompt then appears, and the application runs.

Example script:

Code: Select all

#singleinstance force
#include <RunAsTask>
RunAsTask()

Gui, Add, Edit
Gui Show, x0 y0

return

GuiClose:
	ExitApp
Gweek
Posts: 64
Joined: 24 Sep 2015, 06:29

Re: RunAsTask() - Auto-elevates script without UAC prompt

16 Dec 2015, 21:07

joedf wrote:Oh! Nice, very interesting, I'll have to try it when I return from my trip, thanks for sharing. :)

Edit: cool, Reading from argv pointer!
You are about too read some bad english. and i am really sorry about it i am not a native english speaker

Hey joedf how are U ? hope you are fine :)
i just started using Ahk. and i too don't like UAC prompts .until now i was using task scheduler to skip UAC prompts but now i think i could handle this problem with the help of ahk

so can you plz tell me this script that SKAN created .its only able to skip uac only when i write application name on this script what i want is universal action i want to run this script and boom every application skips uac.
so can you plz tell me how should i modify this script for my use & plz understand i am just foolish noob so plz bear with me

some important facts
i am running windows 10 and don't want to disable uac for some specific reasons
when i run this script every program i click or opens indirectly will skip UAC.
i do a lot of networking work safely without uac on windows 7 but rightnow i have to done some of my works on windows 10 so i want to make this script to easy my burden(UAC are time consuming )

thanxx plz relpy i came here with a lot of hope so plz dont break my hope
User avatar
joedf
Posts: 8937
Joined: 29 Sep 2013, 17:08
Location: Canada
Contact:

Re: RunAsTask() - Auto-elevates script without UAC prompt

17 Dec 2015, 16:38

Well that would be a big security breach... You could have a "central" executable run all your other scripts since the rights will be inherited.
Image Image Image Image Image
Windows 10 x64 Professional, Intel i5-8500, NVIDIA GTX 1060 6GB, 2x16GB Kingston FURY Beast - DDR4 3200 MHz | [About Me] | [About the AHK Foundation] | [Courses on AutoHotkey]
[ASPDM - StdLib Distribution] | [Qonsole - Quake-like console emulator] | [LibCon - Autohotkey Console Library]
Gweek
Posts: 64
Joined: 24 Sep 2015, 06:29

Re: RunAsTask() - Auto-elevates script without UAC prompt

17 Dec 2015, 18:13

joedf wrote:Well that would be a big security breach... You could have a "central" executable run all your other scripts since the rights will be inherited.
I already know the consequences and so i already bought 24/7 backup station in the case my windows fuckup so plz Now i just want your help that's all i want

Thanxx

Return to “Scripts and Functions (v1)”

Who is online

Users browsing this forum: chinagreenelvis, MrDoge, TheNaviator and 84 guests