Cómo ejecutar un script de python con privilegios elevados en Windows
admin elevated-privileges (7)
Estoy escribiendo una aplicación pyqt que requieren para ejecutar la tarea de administración. Preferiría comenzar mi script con elevar el privilegio. Soy consciente de que esta pregunta se hace muchas veces en SO o en otro foro. Pero la solución que la gente está sugiriendo es echar un vistazo a esta pregunta de SO. Solicitar elevación de UAC desde dentro de un script de Python.
Sin embargo, no puedo ejecutar el código de muestra que figura en el enlace. Puse este código en la parte superior del archivo principal y traté de ejecutarlo.
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)
print "I am root now."
De hecho, pide permiso para elevar, pero la línea de impresión nunca se ejecuta. Alguien puede ayudarme a ejecutar el código anterior con éxito. Gracias por adelantado.
Además, si su directorio de trabajo es diferente de lo que puede usar lpDirectory
procInfo = ShellExecuteEx(nShow=showCmd,
lpVerb=lpVerb,
lpFile=cmd,
lpDirectory= unicode(direc),
lpParameters=params)
Será útil si cambiar la ruta no es una opción deseable eliminar unicode para python 3.X
Aquí hay una solución con una redirección estándar:
def elevate():
import ctypes, win32com.shell.shell, win32event, win32process
outpath = r''%s/%s.out'' % (os.environ["TEMP"], os.path.basename(__file__))
if ctypes.windll.shell32.IsUserAnAdmin():
if os.path.isfile(outpath):
sys.stderr = sys.stdout = open(outpath, ''w'', 0)
return
with open(outpath, ''w+'', 0) as outfile:
hProc = win32com.shell.shell.ShellExecuteEx(lpFile=sys.executable, /
lpVerb=''runas'', lpParameters='' ''.join(sys.argv), fMask=64, nShow=0)[''hProcess'']
while True:
hr = win32event.WaitForSingleObject(hProc, 40)
while True:
line = outfile.readline()
if not line: break
sys.stdout.write(line)
if hr != 0x102: break
os.remove(outpath)
sys.stderr = ''''
sys.exit(win32process.GetExitCodeProcess(hProc))
if __name__ == ''__main__'':
elevate()
main()
Aquí hay una solución que solo necesita el módulo ctypes. Admite el programa envuelto de pyinstaller.
#!python
# coding: utf-8
import sys
import ctypes
def run_as_admin(argv=None, debug=False):
shell32 = ctypes.windll.shell32
if argv is None and shell32.IsUserAnAdmin():
return True
if argv is None:
argv = sys.argv
if hasattr(sys, ''_MEIPASS''):
# Support pyinstaller wrapped program.
arguments = map(unicode, argv[1:])
else:
arguments = map(unicode, argv)
argument_line = u'' ''.join(arguments)
executable = unicode(sys.executable)
if debug:
print ''Command line: '', executable, argument_line
ret = shell32.ShellExecuteW(None, u"runas", executable, argument_line, None, 1)
if int(ret) <= 32:
return False
return None
if __name__ == ''__main__'':
ret = run_as_admin()
if ret is True:
print ''I have admin privilege.''
raw_input(''Press ENTER to exit.'')
elif ret is None:
print ''I am elevating to admin privilege.''
raw_input(''Press ENTER to exit.'')
else:
print ''Error(ret=%d): cannot elevate privilege.'' % (ret, )
Encontré una solución muy fácil a este problema.
- Crear un acceso directo para
python.exe
- Cambie el destino del acceso directo a algo como
C:/xxx/.../python.exe your_script.py
- Haga clic en "avanzar ..." en el panel de propiedades del acceso directo, y haga clic en la opción "ejecutar como administrador"
No estoy seguro de si los hechizos de estas opciones son correctos, ya que estoy usando la versión china de Windows.
Gracias a todos por su respuesta. Tengo mi guión trabajando con el módulo / guión escrito por Preston Landers en el año 2010. Después de dos días de navegar por Internet pude encontrar el guión tal como estaba, que estaba profundamente escondido en la lista de correo de pywin32. Con esta secuencia de comandos, es más fácil verificar si el usuario es administrador y, en caso negativo, solicitar el derecho de administrador / UAC. Proporciona salida en ventanas separadas para descubrir qué está haciendo el código. Ejemplo sobre cómo usar el código también incluido en el script. Para el beneficio de todos los que buscan el UAC en Windows, echen un vistazo a este código. Espero que ayude a alguien que busca la misma solución. Se puede usar algo como esto desde tu script principal:
import admin
if not admin.isUserAdmin():
admin.runAsAdmin()
El código real es: -
#!/usr/bin/env python
# -*- coding: utf-8; mode: python; py-indent-offset: 4; indent-tabs-mode: nil -*-
# vim: fileencoding=utf-8 tabstop=4 expandtab shiftwidth=4
# (C) COPYRIGHT © Preston Landers 2010
# Released under the same license as Python 2.6.5
import sys, os, traceback, types
def isUserAdmin():
if os.name == ''nt'':
import ctypes
# WARNING: requires Windows XP SP2 or higher!
try:
return ctypes.windll.shell32.IsUserAnAdmin()
except:
traceback.print_exc()
print "Admin check failed, assuming not an admin."
return False
elif os.name == ''posix'':
# Check for root on Posix
return os.getuid() == 0
else:
raise RuntimeError, "Unsupported operating system for this module: %s" % (os.name,)
def runAsAdmin(cmdLine=None, wait=True):
if os.name != ''nt'':
raise RuntimeError, "This function is only implemented on Windows."
import win32api, win32con, win32event, win32process
from win32com.shell.shell import ShellExecuteEx
from win32com.shell import shellcon
python_exe = sys.executable
if cmdLine is None:
cmdLine = [python_exe] + sys.argv
elif type(cmdLine) not in (types.TupleType,types.ListType):
raise ValueError, "cmdLine is not a sequence."
cmd = ''"%s"'' % (cmdLine[0],)
# XXX TODO: isn''t there a function or something we can call to massage command line params?
params = " ".join([''"%s"'' % (x,) for x in cmdLine[1:]])
cmdDir = ''''
showCmd = win32con.SW_SHOWNORMAL
#showCmd = win32con.SW_HIDE
lpVerb = ''runas'' # causes UAC elevation prompt.
# print "Running", cmd, params
# ShellExecute() doesn''t seem to allow us to fetch the PID or handle
# of the process, so we can''t get anything useful from it. Therefore
# the more complex ShellExecuteEx() must be used.
# procHandle = win32api.ShellExecute(0, lpVerb, cmd, params, cmdDir, showCmd)
procInfo = ShellExecuteEx(nShow=showCmd,
fMask=shellcon.SEE_MASK_NOCLOSEPROCESS,
lpVerb=lpVerb,
lpFile=cmd,
lpParameters=params)
if wait:
procHandle = procInfo[''hProcess'']
obj = win32event.WaitForSingleObject(procHandle, win32event.INFINITE)
rc = win32process.GetExitCodeProcess(procHandle)
#print "Process handle %s returned code %s" % (procHandle, rc)
else:
rc = None
return rc
def test():
rc = 0
if not isUserAdmin():
print "You''re not an admin.", os.getpid(), "params: ", sys.argv
#rc = runAsAdmin(["c://Windows//notepad.exe"])
rc = runAsAdmin()
else:
print "You are an admin!", os.getpid(), "params: ", sys.argv
rc = 0
x = raw_input(''Press Enter to exit.'')
return rc
if __name__ == "__main__":
sys.exit(test())
Puedo confirmar que la solución de delphifirst funciona y es la solución más simple y sencilla al problema de ejecutar un script de Python con privilegios elevados.
Creé un acceso directo al ejecutable de python (python.exe) y luego modifiqué el acceso directo agregando el nombre de mi script después de la llamada a python.exe. Luego marqué "ejecutar como administrador" en la "pestaña de compatibilidad" del acceso directo. Cuando se ejecuta el acceso directo, se le solicita que solicite permiso para ejecutar el script como administrador.
Mi aplicación Python particular fue un programa instalador. El programa permite instalar y desinstalar otra aplicación de Python. En mi caso, creé dos accesos directos, uno llamado "appname install" y el otro llamado "appname uninstall". La única diferencia entre los dos atajos es el argumento que sigue al nombre del script de python. En la versión del instalador, el argumento es "instalar". En la versión de desinstalación, el argumento es "desinstalar". El código en el script del instalador evalúa el argumento proporcionado y llama a la función apropiada (instalar o desinstalar) según sea necesario.
Espero que mi explicación ayude a otros a descubrir más rápidamente cómo ejecutar un script de Python con privilegios elevados.
en los comentarios a la respuesta que tomó el código de alguien dice que ShellExecuteEx no publica su STDOUT de vuelta al shell de origen . por lo que no verá "Ahora soy root", aunque el código probablemente funcione bien.
en lugar de imprimir algo, intente escribir en un archivo:
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)
with open("somefilename.txt", "w") as out:
print >> out, "i am root"
y luego mira en el archivo.