As of 2017, an easy method to achieve this is the following:

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, " ".join(sys.argv), None, 1)

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

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

Also note that if you converted you python script into an executable file (using tools like py2exe, cx_freeze, pyinstaller) then you should use sys.argv[1:] instead of sys.argv in the fourth parameter.

Some of the advantages here are:

  • No external libraries required. It only uses ctypes and sys from standard library.
  • Works on both Python 2 and Python 3.
  • There is no need to modify the file resources nor creating a manifest file.
  • If you don't add code below if/else statement, the code won't ever be executed twice.
  • You can get the return value of the API call in the last line and take an action if it fails (code <= 32). Check possible return values here.
  • You can change the display method of the spawned process modifying the sixth parameter.

Documentation for the underlying ShellExecute call is here.

Answer from Martín De la Fuente on Stack Overflow
Top answer
1 of 12
159

As of 2017, an easy method to achieve this is the following:

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, " ".join(sys.argv), None, 1)

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

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

Also note that if you converted you python script into an executable file (using tools like py2exe, cx_freeze, pyinstaller) then you should use sys.argv[1:] instead of sys.argv in the fourth parameter.

Some of the advantages here are:

  • No external libraries required. It only uses ctypes and sys from standard library.
  • Works on both Python 2 and Python 3.
  • There is no need to modify the file resources nor creating a manifest file.
  • If you don't add code below if/else statement, the code won't ever be executed twice.
  • You can get the return value of the API call in the last line and take an action if it fails (code <= 32). Check possible return values here.
  • You can change the display method of the spawned process modifying the sixth parameter.

Documentation for the underlying ShellExecute call is here.

2 of 12
73

It took me a little while to get dguaraglia's answer working, so in the interest of saving others time, here's 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)
Top answer
1 of 2
1

The ShellExecute API call will spawn a new process, it won't elevate permissions for the current process running.

Let's analyze this code snippet:

if is_admin():
    main()
else:
    ctypes.windll.shell32.ShellExecuteW(None, "runas", sys.executable, " ".join(sys.argv), None, 1)

When you first run this Python script without privileges, this initial process will jump to the last line of the code because is_admin returns False. Once there, the UAC prompt is displayed.

  • If the UAC prompt is accepted, then a completely new process (with different process ID) is created and the code is executed again (from the beginning), but this time with admin privileges. Now is_admin should return True and main should be called.
  • If the UAC prompt is rejected, no new process is created.

Regardless of the UAC response, the initial process will get the return code back, but its privileges will remain unaltered.

If you want to try this yourself, add an input() at the end of the file and you should be able to see two different windows after accepting the UAC prompt.

To avoid having your code being executed twice be sure to keep everything inside the main function. If you want to take an action based on the return code, this only makes sense for failures (code <= 32). If the return code is successfull (> 32), then the process should end gracefully and let the new spawned process do its job.

2 of 2
0
import ctypes
import sys
import platform

def admin() -> "Admin Bool":
    """Requests UAC Admin on Windows with a prompt"""
    if platform.system() == "Windows":
        ctypes.windll.shell32.ShellExecuteW(
            None,
            'runas',
            sys.executable,
            ' '.join(sys.argv),
            None,
            None
        )
        
        try:
            return ctypes.windll.shell32.IsUserAnAdmin()
        
        except:
            return False
        
    else:
        raise OSError("admin() only works for windows.")

This will request admin with an admin prompt. If True is returned, then admin has been granted by the user. Else, False will be returned.

🌐
Sourcecodequery
sourcecodequery.com › example-method › ctypes.windll.shell32.ShellExecuteW
SourceCodeQuery - Python ctypes.windll.shell32.ShellExecuteW Examples
def _bind_apk_right_menu(): if not ctypes.windll.shell32.IsUserAnAdmin(): ctypes.windll.shell32.ShellExecuteW( None, "runas", sys.executable, __file__ + " --bind", None, 0) return with winreg.OpenKey(winreg.HKEY_CLASSES_ROOT, r"*\shell") as key: print(key) with winreg.CreateKeyEx(key, "APK Parser", 0, winreg.KEY_SET_VALUE) as shell_key: icon_path = str(pathlib.Path(__file__).joinpath( "../android.ico").resolve()) winreg.SetValueEx(shell_key, "Icon", 0, winreg.REG_SZ, icon_path) with winreg.CreateKey(shell_key, "command") as cmd_key: winreg.SetValue( cmd_key, "", 1, " ".join( [sys.executable.replace("python.exe", "pythonw.exe"), os.path.abspath(__file__), "--file", "\"%1\""])) File: __main__.py ·
🌐
GitHub
github.com › JustAMan › pyWinClobber › blob › master › win32elevate.py
pyWinClobber/win32elevate.py at master · JustAMan/pyWinClobber
ShellExecuteEx = ctypes.windll.Shell32.ShellExecuteExA · ShellExecuteEx.argtypes = (PShellExecuteInfo, ) ShellExecuteEx.restype = BOOL · · WaitForSingleObject = ctypes.windll.kernel32.WaitForSingleObject · WaitForSingleObject.argtypes = (HANDLE, DWORD) WaitForSingleObject.restype = DWORD ·
Author: JustAMan
🌐
Coderanch
coderanch.com › t › 751099 › languages › python
python (Jython/Python forum at Coderanch)
April 20, 2022 - import ctypes, subprocess,shutil ,sys ctypes.windll.shell32.ShellExecuteW(None, "runas", sys.executable, " ".join(sys.argv), None, 1) subprocess.call(['C:\\Windows\\notepad.exe', 'C:\Windows\System32\drivers\etc\hosts']) append = open('C:\Windows\System32\drivers\etc\hosts','a').write("127.0.0.1 www.google.com") print(append.read()) # want to append hosts file as administrator
🌐
GitHub
gist.github.com › TotalLag › f85eaf831c29b3a411a69187d9eef317
Re-run the program with admin rights in Python · GitHub
Re-run the program with admin rights in Python. GitHub Gist: instantly share code, notes, and snippets.
Find elsewhere
🌐
GitHub
github.com › AirtestProject › AirtestIDE › issues › 1015
调用“ctypes.windll.shell32.ShellExecuteW(None, "runas", sys.executable, __file__, None, 1)”报错 · Issue #1015 · AirtestProject/AirtestIDE
October 17, 2021 - def is_admin(): try: return ctypes.windll.shell32.IsUserAnAdmin() except: return False if is_admin(): # 将要运行的代码加到这里 else: ctypes.windll.shell32.ShellExecuteW(None, "runas", sys.executable, file, None, 1)
Author: AirtestProject
🌐
ProgramCreek
programcreek.com › python › example › 68647 › ctypes.windll.shell32
Python Examples of ctypes.windll.shell32
# pylint: disable=no-name-in-module,F0401 from ctypes import byref, c_int, POINTER, windll, WINFUNCTYPE from ctypes.wintypes import LPCWSTR, LPWSTR # <http://msdn.microsoft.com/en-us/library/ms683156.aspx> GetCommandLineW = WINFUNCTYPE(LPWSTR)(('GetCommandLineW', windll.kernel32)) # <http://msdn.microsoft.com/en-us/library/bb776391.aspx> CommandLineToArgvW = WINFUNCTYPE(POINTER(LPWSTR), LPCWSTR, POINTER(c_int))( ('CommandLineToArgvW', windll.shell32)) argc = c_int(0) argv_unicode = CommandLineToArgvW(GetCommandLineW(), byref(argc)) argv = [ argv_unicode[i].encode(encoding, 'replace') for i in range(0, argc.value) ] if not hasattr(sys, 'frozen'): # If this is an executable produced by py2exe or bbfreeze, then it # will have been invoked directly.
Top answer
1 of 2
2

It looks like types.TupleType and types.ListType do not exist in Python 3. Try the following instead:

elif type(cmdLine) not in (tuple, list)

The value error after saying that "cmdLine is not a sequence" is not exactly accurate because strings are sequences, but should indeed raise a ValueError. I might reword it to "cmdLine should be a non-empty tuple or list, or None." You could update it to more broadly check whether cmdLine is a non-string iterable, but that might be overkill.

2 of 2
2

The following example demonstrates a simple way to have a program run with elevated privileges on Windows. The enumerations are meant to simplify some values needed when interacting with the operating system. The first allows for easy specification of how an elevated program is to be opened, and the second helps when errors need to be easily identified. Please note that if you want all command line arguments 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


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:
        hinstance = ctypes.windll.shell32.ShellExecuteW(
            None, 'runas', sys.executable, sys.argv[0], None, SW.SHOWNORMAL
        )
        if hinstance <= 32:
            raise RuntimeError(ERROR(hinstance))


def main():
    # Your Code Here
    print(input('Echo: '))


if __name__ == '__main__':
    bootstrap()
🌐
Python Forum
python-forum.io › thread-11767.html
Registry Key Access
How can I get access to an administrator-level access registry key via code? I read this article linked in the official docs, but I'm not sure where to go. The straight forward method is not working. Apparently I need to take ownership of the key?...
🌐
Python
docs.python.org › 3 › library › ctypes.html
ctypes — A foreign function library for Python
Class which loads shared libraries. dlltype should be one of the CDLL, PyDLL, WinDLL, or OleDLL types.
🌐
0x00sec
archive.0x00sec.org › t › python-and-malware-writing-a-simple-wiper-malware › 31652
0x00sec - The Home of the Hacker
October 11, 2022 - The Home of the Hacker - Malware, Reverse Engineering, and Computer Science.
🌐
Stack Overflow
stackoverflow.com › questions › 39306920 › python-shellexecute-windows-api-with-ctypes-over-tcp-ip
Python Shellexecute windows api with Ctypes over TCP/IP - Stack Overflow
September 6, 2016 - import socket import subprocess import ctypes HOST = '192.168.1.22' PORT = 443 s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.connect((HOST, PORT)) while 1: #send initial cmd.exe banner to remote machine s.send(ctypes.windll.Shell32.ShellExecuteA(None,"open","cmd.exe",None,None,0)) #accept user input data = s.recv(1024) #pass it again to Shellexecute api to execute and return output to remote machine, fully simulating original CMD over TCP/IP s.close()
🌐
GitHub
gist.github.com › princox › 92ad572cde940604adeaedea51cf5848
python execution file · GitHub
python execution file. GitHub Gist: instantly share code, notes, and snippets.