|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
from __future__ import print_function |
|
import sys, os, traceback |
|
from enum import IntEnum |
|
|
|
if sys.version_info < (3,): |
|
text_type = basestring |
|
else: |
|
text_type = str |
|
|
|
|
|
def isUserAdmin(): |
|
|
|
if os.name == 'nt': |
|
import ctypes |
|
|
|
try: |
|
return ctypes.windll.shell32.IsUserAnAdmin() |
|
except: |
|
traceback.print_exc() |
|
print("Admin check failed, assuming not an admin.") |
|
return False |
|
elif os.name == 'posix': |
|
|
|
return os.getuid() == 0 |
|
else: |
|
raise RuntimeError("Unsupported operating system for this module: %s" % (os.name,)) |
|
|
|
|
|
|
|
if os.name == 'nt': |
|
|
|
def ensure_binary(value): |
|
try: |
|
return value.encode('utf-8') |
|
except AttributeError: |
|
|
|
|
|
return value |
|
|
|
from ctypes import (POINTER, Structure, WinError, byref, c_ulong, c_char_p, c_int, |
|
c_void_p, sizeof, windll) |
|
from ctypes.wintypes import HANDLE, BOOL, DWORD, HWND, HINSTANCE, HKEY |
|
PHANDLE = POINTER(HANDLE) |
|
PDWORD = POINTER(DWORD) |
|
SEE_MASK_NOCLOSEPROCESS = 0x00000040 |
|
INFINITE = -1 |
|
|
|
WaitForSingleObject = windll.kernel32.WaitForSingleObject |
|
WaitForSingleObject.argtypes = (HANDLE, DWORD) |
|
WaitForSingleObject.restype = DWORD |
|
|
|
GetExitCodeProcess = windll.kernel32.GetExitCodeProcess |
|
GetExitCodeProcess.argtypes = (HANDLE, PDWORD) |
|
GetExitCodeProcess.restype = BOOL |
|
|
|
class ShellExecuteInfo(Structure): |
|
""" |
|
https://docs.microsoft.com/en-us/windows/desktop/api/shellapi/nf-shellapi-shellexecuteexa |
|
https://docs.microsoft.com/en-us/windows/desktop/api/shellapi/ns-shellapi-_shellexecuteinfoa |
|
""" |
|
|
|
_fields_ = [ |
|
('cbSize', DWORD), |
|
('fMask', c_ulong), |
|
('hwnd', HWND), |
|
('lpVerb', c_char_p), |
|
('lpFile', c_char_p), |
|
('lpParameters', c_char_p), |
|
('lpDirectory', c_char_p), |
|
('nShow', c_int), |
|
('hInstApp', HINSTANCE), |
|
('lpIDList', c_void_p), |
|
('lpClass', c_char_p), |
|
('hKeyClass', HKEY), |
|
('dwHotKey', DWORD), |
|
('hIcon', HANDLE), |
|
('hProcess', HANDLE) |
|
] |
|
|
|
def __init__(self, **kwargs): |
|
Structure.__init__(self) |
|
self.cbSize = sizeof(self) |
|
for field_name, field_value in kwargs.items(): |
|
if isinstance(field_value, str): |
|
field_value = ensure_binary(field_value) |
|
setattr(self, field_name, field_value) |
|
|
|
PShellExecuteInfo = POINTER(ShellExecuteInfo) |
|
ShellExecuteEx = windll.Shell32.ShellExecuteExA |
|
ShellExecuteEx.argtypes = (PShellExecuteInfo, ) |
|
ShellExecuteEx.restype = BOOL |
|
|
|
|
|
class SW(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 |
|
|
|
|
|
def runAsAdmin(cmdLine=None, wait=True): |
|
if os.name != 'nt': |
|
raise RuntimeError("This function is only implemented on Windows.") |
|
|
|
python_exe = sys.executable |
|
|
|
if cmdLine is None: |
|
cmdLine = [python_exe] + sys.argv |
|
elif not hasattr(cmdLine, "__iter__") or isinstance(cmdLine, text_type): |
|
raise ValueError("cmdLine is not a sequence.") |
|
|
|
cmd = '"%s"' % (cmdLine[0],) |
|
|
|
params = " ".join(['"%s"' % (x,) for x in cmdLine[1:]]) |
|
showCmd = SW.HIDE |
|
lpVerb = 'runas' |
|
|
|
|
|
|
|
|
|
|
|
|
|
execute_info = ShellExecuteInfo(nShow=showCmd, |
|
fMask=SEE_MASK_NOCLOSEPROCESS, |
|
lpVerb=lpVerb, |
|
lpFile=cmd, |
|
lpParameters=params, |
|
hwnd=None, |
|
lpDirectory=None) |
|
|
|
successful = ShellExecuteEx(byref(execute_info)) |
|
|
|
if not successful: |
|
raise WinError() |
|
|
|
if wait: |
|
procHandle = execute_info.hProcess |
|
WaitForSingleObject(procHandle, INFINITE) |
|
err = DWORD() |
|
GetExitCodeProcess(procHandle, byref(err)) |
|
rc = err.value |
|
else: |
|
rc = None |
|
|
|
return rc |
|
|
|
|
|
if __name__ == '__main__': |
|
userIsAdmin = isUserAdmin() |
|
print('userIsAdmin = %d' % (userIsAdmin)) |
|
if not userIsAdmin: |
|
runAsAdmin([sys.executable] + sys.argv, wait=True) |
|
|