Cómo ejecutar script python con privilegios elevados en Windows
Estoy escribiendo una aplicación pyqt que requiere ejecutar la tarea admin. Preferiría comenzar mi guión con elevate privilege. Soy consciente de que esta pregunta se hace muchas veces en tal o cual foro. Pero la solución que la gente está sugiriendo es echar un vistazo a esta pregunta ¿Solicitar la elevación de UAC desde un script Python?
Sin embargo, no puedo ejecutar el código de ejemplo dado en el enlace. He puesto este código encima del archivo principal y he intentado 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."
En realidad 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 de antemano.
7 answers
Gracias a todos por su respuesta. Tengo mi guión trabajando con el módulo / guión escrito por Preston Landers en 2010. Después de dos días de navegar por Internet, pude encontrar el script tal como estaba profundamente oculto en la lista de correo de pywin32. Con este script es más fácil comprobar si el usuario es administrador y si no, entonces preguntar por UAC/ admin derecho. Proporciona salida en ventanas separadas para averiguar qué está haciendo el código. Ejemplo de cómo usar el código también incluido en el script. Para el beneficio de todos los que todos están buscando UAC en Windows echar un vistazo a este código. Espero que ayude a alguien que busca la misma solución. Se puede usar algo como esto desde su 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())
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-11-01 01:06:42
En los comentarios a la respuesta tomaste el código de alguien dice ShellExecuteEx no envía su salida estándar al shell de origen. así que no verás "Soy root ahora", a pesar de que el código probablemente está funcionando 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 busque en el archivo.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 12:10:29
Aquí hay una solución con una redirección stdout:
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()
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-07-20 06:11:37
Aquí hay una solución que solo necesitaba el módulo ctypes. Soporte pyinstaller envuelto programa.
#!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, )
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-11-22 14:58:34
Encontré una solución muy fácil a este problema.
- Crear un acceso directo para
python.exe
- Cambie el objetivo de 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.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-09-21 15:49:49
Puedo confirmar que la solución de delphifirst funciona y es la solución más fácil y sencilla al problema de ejecutar un script python con privilegios elevados.
He creado un acceso directo al ejecutable de python (python.exe) y luego modificó el atajo agregando el nombre de mi script después de la llamada a python.exe. A continuación, he marcado "ejecutar como administrador" en la "pestaña de compatibilidad" del acceso directo. Cuando se ejecuta el acceso directo, se obtiene un mensaje pidiendo permiso para ejecutar el script como un administrador.
Mi aplicación particular de python era un programa de instalación. El programa permite instalar y desinstalar otra aplicación python. En mi caso he creado dos accesos directos, uno llamado " appname install "y el otro llamado"appname uninstall". La única diferencia entre los dos accesos directos es el argumento que sigue al nombre del script python. En la versión del instalador el argumento es "install". En la versión de desinstalación el argumento es "desinstalar". El código en el script de instalación evalúa el argumento suministrado 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 python con privilegios elevados.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-12-06 17:32:33
También si su directorio de trabajo es diferente de lo que puede utilizar 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
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-02-28 06:13:36