Request UAC boost from Python script?

I want my Python script to copy files in Vista. When I run it from a regular cmd.exe window, no errors are generated, but the files are NOT copied. If I run cmd.exe "as administrator" and then run my script, it works fine.

This makes sense because User Account Control (UAC) typically prevents many file system actions.

Is there a way, from within a Python script, to call a request to raise UAC (those dialogs that say something like "such and such an application needs administrator access, is this normal?")

If this is not possible, is there a way in which my script can at least detect that it is not promoted so that it can fail gracefully?

+74
python windows windows-vista uac
Sep 25 '08 at 0:22
source share
10 answers

As of 2017, an easy way to achieve this is as follows:

 import ctypes, sys def is_admin(): try: return ctypes.windll.shell32.IsUserAnAdmin() except: return False if is_admin(): # Code of your program here else: # Re-run the program with admin rights ctypes.windll.shell32.ShellExecuteW(None, "runas", sys.executable, __file__, None, 1) 

If you are using Python 2.x, you should replace the last line:

 ctypes.windll.shell32.ShellExecuteW(None, u"runas", unicode(sys.executable), unicode(__file__), None, 1) 

Also note that if you converted the python script to an executable file (using tools such as py2exe , cx_freeze , pyinstaller ), you must replace the fourth parameter with an empty string ( "" ).

Here are some of the benefits:

  • No external libraries are required (as well as the Python extension for Windows). It uses only ctypes from the standard library.
  • Works on both Python 2 and Python 3.
  • There is no need to modify file resources or create a manifest file.
  • If you do not add the code below, if / else, the code will never be executed twice.
  • You can easily change it to have special behavior if the user rejects the UAC invitation.
  • You can specify arguments that change the fourth parameter.
  • You can specify a display method that changes the sixth parameter.

The documentation for the main ShellExecute call is here .

+60
Jan 30 '17 at 7:10
source share
— -

It took me a little time to get dguaraglia's answer, so in the interest of saving other times, here is what I did to implement this idea:

 import os import sys import win32com.shell.shell as shell ASADMIN = 'asadmin' if sys.argv[-1] != ASADMIN: script = os.path.abspath(sys.argv[0]) params = ' '.join([script] + sys.argv[1:] + [ASADMIN]) shell.ShellExecuteEx(lpVerb='runas', lpFile=sys.executable, lpParameters=params) sys.exit(0) 
+62
Jul 31 '12 at 18:09
source share

It seems that it is incorrect to raise the privileges of an application to perform a specific task. Windows should know at the beginning of the program whether the application requires certain rights, and will ask the user to confirm when the application performs any tasks that require these privileges. There are two ways to do this:

  • Writing a manifest file that Windows tells you may require some privileges for the application
  • Run the elevated application from another program

This two articles explain in much more detail how this works.

What would I do if you do not want to write the nasty ctypes shell for the CreateElevatedProcess API, the ShellExecuteEx trick described in the Code Project article (Pywin32 comes with a shell for ShellExecute) is used. How? Something like that:

When your program starts, it checks whether it has administrator rights, if it does not start itself with the ShellExecute trick and immediately exits, if so, it performs the task at hand.

As you describe your program as a "script", I believe this is enough for your needs.

Greetings.

+28
Sep 25 '08 at 2:01
source share

The recognition of this question was asked a few years ago, I think a more elegant solution is offered on github using frmdstryr using its pyminutils module:

Excerpts:

 import pythoncom from win32com.shell import shell,shellcon def copy(src,dst,flags=shellcon.FOF_NOCONFIRMATION): """ Copy files using the built in Windows File copy dialog Requires absolute paths. Does NOT create root destination folder if it doesn't exist. Overwrites and is recursive by default @see http://msdn.microsoft.com/en-us/library/bb775799(v=vs.85).aspx for flags available """ # @see IFileOperation pfo = pythoncom.CoCreateInstance(shell.CLSID_FileOperation,None,pythoncom.CLSCTX_ALL,shell.IID_IFileOperation) # Respond with Yes to All for any dialog # @see http://msdn.microsoft.com/en-us/library/bb775799(v=vs.85).aspx pfo.SetOperationFlags(flags) # Set the destionation folder dst = shell.SHCreateItemFromParsingName(dst,None,shell.IID_IShellItem) if type(src) not in (tuple,list): src = (src,) for f in src: item = shell.SHCreateItemFromParsingName(f,None,shell.IID_IShellItem) pfo.CopyItem(item,dst) # Schedule an operation to be performed # @see http://msdn.microsoft.com/en-us/library/bb775780(v=vs.85).aspx success = pfo.PerformOperations() # @see sdn.microsoft.com/en-us/library/bb775769(v=vs.85).aspx aborted = pfo.GetAnyOperationsAborted() return success is None and not aborted 

This uses the COM interface and automatically indicates that you need administrator privileges with the familiar dialog hint that you will see if you copied to a directory where administrator privileges are needed, and also provides a typical file progress dialog during a copy operation.

+4
Aug 26 '15 at 15:03
source share

The following example is based on the excellent work of Martin de la Fuente Saavedra and the accepted answer. In particular, two enumerations are introduced. The first makes it easy to determine how to open a program with elevated rights, and the second helps when it is necessary to easily identify errors. Note that if you want all command line arguments to be passed to the new process, sys.argv[0] should probably be replaced with a function call: subprocess.list2cmdline(sys.argv) .

 #! /usr/bin/env python3 import ctypes import enum import sys # Reference: # msdn.microsoft.com/en-us/library/windows/desktop/bb762153(v=vs.85).aspx # noinspection SpellCheckingInspection class SW(enum.IntEnum): HIDE = 0 MAXIMIZE = 3 MINIMIZE = 6 RESTORE = 9 SHOW = 5 SHOWDEFAULT = 10 SHOWMAXIMIZED = 3 SHOWMINIMIZED = 2 SHOWMINNOACTIVE = 7 SHOWNA = 8 SHOWNOACTIVATE = 4 SHOWNORMAL = 1 class ERROR(enum.IntEnum): ZERO = 0 FILE_NOT_FOUND = 2 PATH_NOT_FOUND = 3 BAD_FORMAT = 11 ACCESS_DENIED = 5 ASSOC_INCOMPLETE = 27 DDE_BUSY = 30 DDE_FAIL = 29 DDE_TIMEOUT = 28 DLL_NOT_FOUND = 32 NO_ASSOC = 31 OOM = 8 SHARE = 26 def bootstrap(): if ctypes.windll.shell32.IsUserAnAdmin(): main() else: # noinspection SpellCheckingInspection hinstance = ctypes.windll.shell32.ShellExecuteW( None, 'runas', sys.executable, subprocess.list2cmdline(sys.argv), None, SW.SHOWNORMAL ) if hinstance <= 32: raise RuntimeError(ERROR(hinstance)) def main(): # Your Code Here print(input('Echo: ')) if __name__ == '__main__': bootstrap() 
+3
Mar 14 '17 at 13:35
source share

This may not completely answer your question, but you can also try using the Elevate Powertoy command to run the script with elevated UAC privileges.

http://technet.microsoft.com/en-us/magazine/2008.06.elevation.aspx

I think that if you use it, it will look like "raise python yourscript.py"

+2
Sep 24 '10 at 13:43
source share

If your script always requires administrator privileges, then:

 runas /user:Administrator "python your_script.py" 
+1
Sep 26 '08 at 11:54
source share

You can make a shortcut somewhere and use the target: python yourscript.py then, by properties and advanced selection, starts as an administrator.

When the user runs the shortcut, he will ask them to lift the application.

+1
Apr 02 '14 at 19:56
source share

Jorenko's work option above allows the elevated process to use the same console (but see my comment below):

 def spawn_as_administrator(): """ Spawn ourself with administrator rights and wait for new process to exit Make the new process use the same console as the old one. Raise Exception() if we could not get a handle for the new re-run the process Raise pywintypes.error() if we could not re-spawn Return the exit code of the new process, or return None if already running the second admin process. """ #pylint: disable=no-name-in-module,import-error import win32event, win32api, win32process import win32com.shell.shell as shell if '--admin' in sys.argv: return None script = os.path.abspath(sys.argv[0]) params = ' '.join([script] + sys.argv[1:] + ['--admin']) SEE_MASK_NO_CONSOLE = 0x00008000 SEE_MASK_NOCLOSE_PROCESS = 0x00000040 process = shell.ShellExecuteEx(lpVerb='runas', lpFile=sys.executable, lpParameters=params, fMask=SEE_MASK_NO_CONSOLE|SEE_MASK_NOCLOSE_PROCESS) hProcess = process['hProcess'] if not hProcess: raise Exception("Could not identify administrator process to install drivers") # It is necessary to wait for the elevated process or else # stdin lines are shared between 2 processes: they get one line each INFINITE = -1 win32event.WaitForSingleObject(hProcess, INFINITE) exitcode = win32process.GetExitCodeProcess(hProcess) win32api.CloseHandle(hProcess) return exitcode 
+1
Dec 11 '15 at 5:34
source share

This is basically an update to Jorenko’s answer, allowing you to use parameters with spaces in Windows, but should also work well on Linux :) It will also work with cx_freeze or py2exe, since we do not use __file__ but sys.argv[0] as an executable file

 import sys,ctypes,platform def is_admin(): try: return ctypes.windll.shell32.IsUserAnAdmin() except: raise False if __name__ == '__main__': if platform.system() == "Windows": if is_admin(): main(sys.argv[1:]) else: # Re-run the program with admin rights, don't use __file__ since py2exe won't know about it # Use sys.argv[0] as script path and sys.argv[1:] as arguments, join them as lpstr, quoting each parameter or spaces will divide parameters lpParameters = "" # Litteraly quote all parameters which get unquoted when passed to python for i, item in enumerate(sys.argv[0:]): lpParameters += '"' + item + '" ' try: ctypes.windll.shell32.ShellExecuteW(None, "runas", sys.executable, lpParameters , None, 1) except: sys.exit(1) else: main(sys.argv[1:]) 
+1
Apr 10 '18 at 16:52
source share



All Articles