script que pasar parametros parametro linea español comando argumentos python windows windows-vista uac

que - ¿Solicitar elevación de UAC desde dentro de un script de Python?



que es argv en python (10)

A partir de 2017, un método fácil de lograr esto es el siguiente:

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)

Si está utilizando Python 2.x, entonces debe reemplazar la última línea por:

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

También tenga en cuenta que si convirtió su secuencia de comandos python en un archivo ejecutable (utilizando herramientas como py2exe , cx_freeze , pyinstaller ), entonces debe reemplazar el cuarto parámetro por una cadena vacía ( "" ).

Algunas de las ventajas aquí son:

  • No se requieren bibliotecas externas (ni la extensión de Python para Windows). Solo utiliza los ctypes de la biblioteca estándar.
  • Funciona tanto en Python 2 como en Python 3.
  • No es necesario modificar los recursos del archivo ni crear un archivo de manifiesto.
  • Si no agrega el código debajo de la declaración if / else, el código nunca se ejecutará dos veces.
  • Puede modificarlo fácilmente para que tenga un comportamiento especial si el usuario rechaza el aviso de UAC.
  • Puede especificar argumentos modificando el cuarto parámetro.
  • Puede especificar el método de visualización que modifica el sexto parámetro.

La documentación para la llamada ShellExecute subyacente está here .

Quiero que mi script de Python copie archivos en Vista. Cuando lo ejecuto desde una ventana cmd.exe normal, no se generan errores, pero los archivos NO se copian. Si ejecuto cmd.exe "como administrador" y luego ejecuto mi script, funciona bien.

Esto tiene sentido ya que el Control de cuentas de usuario (UAC) normalmente evita muchas acciones del sistema de archivos.

¿Hay alguna manera de que, desde dentro de un script de Python, invoque una solicitud de elevación de UAC (esos diálogos que dicen algo como "tal o cual aplicación necesita acceso de administrador, ¿está bien?")

Si eso no es posible, ¿hay alguna manera en que mi script al menos pueda detectar que no está elevado por lo que puede fallar con elegancia?


El siguiente ejemplo se basa en el excelente trabajo de MARTIN DE LA FUENTE SAAVEDRA y la respuesta aceptada. En particular, se introducen dos enumeraciones. El primero permite una fácil especificación de cómo se debe abrir un programa elevado, y el segundo ayuda cuando los errores deben identificarse fácilmente. Tenga en cuenta que si desea que todos los argumentos de la línea de comando pasen al nuevo proceso, sys.argv[0] probablemente debería reemplazarse con una llamada a la función: 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()



Esto es principalmente una actualización de la respuesta de Jorenko, que permite usar parámetros con espacios en Windows, pero también debería funcionar bastante bien en Linux :) Además, funcionará con cx_freeze o py2exe ya que no usamos __file__ sino sys.argv[0] como ejecutable

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:])


Me llevó un poco de tiempo lograr que la respuesta de dguaraglia funcionara, por lo que, con el interés de ahorrarles tiempo a otros, esto es lo que hice para implementar esta 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)


Parece que no hay forma de elevar los privilegios de la aplicación por un tiempo para que pueda realizar una tarea en particular. Windows necesita saber al inicio del programa si la aplicación requiere ciertos privilegios, y le pedirá al usuario que confirme cuándo la aplicación realiza cualquier tarea que necesite esos privilegios. Hay dos maneras de hacer esto:

  1. Escriba un archivo de manifiesto que le indique a Windows que la aplicación podría requerir algunos privilegios
  2. Ejecute la aplicación con privilegios elevados desde dentro de otro programa

Estos two articles explican con mucho más detalle cómo funciona esto.

Lo que haría, si no quiere escribir un contenedor de tipos desagradable para la API CreateElevatedProcess, es usar el truco ShellExecuteEx explicado en el artículo de Code Project (Pywin32 viene con un contenedor para ShellExecute). ¿Cómo? Algo como esto:

Cuando se inicia el programa, comprueba si tiene privilegios de Administrador, si no se ejecuta con el truco ShellExecute y sale inmediatamente, si lo hace, realiza la tarea en cuestión.

Al describir su programa como un "guión", supongo que eso es suficiente para sus necesidades.

Aclamaciones.


Puede hacer un atajo en alguna parte y como destino: python yourscript.py, luego bajo propiedades y selección avanzada ejecutar como administrador.

Cuando el usuario ejecuta el acceso directo, le pedirá que eleve la aplicación.


Reconociendo que esta pregunta se hizo hace años, creo que se ofrece una solución más elegante en github por frmdstryr usando su módulo pyminutils:

Extracto:

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

Esto utiliza la interfaz COM e indica automáticamente que se necesitan privilegios de administrador con el cuadro de diálogo familiar que vería si estuviera copiando en un directorio donde se requieren privilegios de administrador y también proporciona el diálogo de progreso de archivo típico durante la operación de copia.


Si su script siempre requiere los privilegios de un Administrador, entonces:

runas /user:Administrator "python your_script.py"


Una variación del trabajo anterior de Jorenko permite que el proceso elevado use la misma consola (pero vea mi comentario a continuación):

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