2010-11-25 30 views
6

Quelle est la meilleure manière de lancer un sous-processus en tant qu'utilisateur différent sous Python sous Windows? De préférence XP et plus, mais si cela ne fonctionne que sur Vista et 7, je peux vivre avec ça aussi.Sous-processus Python. Ouvrir en tant qu'utilisateur différent sous Windows

+0

je me suis déplacé la réponse publié par @EricPruitt une réponse CW. Si vous voulez le poster vous-même, veuillez republier la réponse vous-même, cingler ici, et je vais supprimer la réponse CW. –

Répondre

5

Je ne sais pas si vous pouvez le faire avec les bibliothèques python standard. Toutefois, le package pywin32 a une fonction win32process.CreateProcessAsUser qui peut être ce dont vous avez besoin.

+1

Existe-t-il un moyen de lire stdout à partir de ça? –

+1

Je ne vois pas un moyen de capturer stdout/err. Toute aide avec ça serait bien. – wesm

+0

Vous pouvez créer un processus python en tant qu'utilisateur cible, faire en sorte que ce processus python exécute votre sous-processus, et transmettre stdin/out/err au processus python "maître", via une connexion socket ou quelque chose comme ça. – pixelbrei

2

Une autre option consiste à remplir non le processus souhaité mais la commande runas .... Notez que le service Run As doit être activé et en cours d'exécution.

0

Je fini par augmenter subprocess:

#!/usr/bin/env python 
# -*- coding: utf-8 -*- 

import subprocess 
import win32con 
import win32process 
import win32security 

from subprocess import * 

__all__ = ["Popen","PIPE", "STDOUT", "call", "check_call", 
    "CalledProcessError", "CREATE_NEW_CONSOLE", "LoginSTARTUPINFO", 
    "STARTUPINFO"] 

class LoginSTARTUPINFO(object): 
    """ 
    Special STARTUPINFO instance that carries login credentials. When a 
    LoginSTARTUPINFO instance is used with Popen, the process will be executed 
    with the credentials used to instantiate the class. 

    If an existing vanilla STARTUPINFO instance needs to be converted, it 
    can be supplied as the last parameter when instantiating LoginSTARTUPINFO. 

    The LoginSTARTUPINFO cannot be used with the regular subprocess module. 

    >>> import subprocesswin32 as subprocess 
    >>> sysuser = LoginSTARTUPINFO("username", "pswd123", "machine") 
    >>> stdout, stderr = subprocess.Popen("cmd.exe", stdout=subprocess.PIPE, 
    ...  startupinfo=sysuser).communicate() 
    """ 
    def __init__(self, username, domain, password, startupinfo=None): 
     m_startupinfo = win32process.STARTUPINFO() 

     # Creates an actual win32 STARTUPINFO class using the attributes 
     # of whatever STARTUPINFO-like object we are passed. 
     for attr in dir(startupinfo): 
      if not(attr.startswith("_") or attr not in dir(m_startupinfo)): 
       setattr(m_startupinfo, attr, getattr(startupinfo, attr)) 

     # Login credentials 
     self.credentials = (username, domain, password) 
     # Proper win32 STARTUPINFO representation for CreateProcess 
     self.win32startupinfo = m_startupinfo 

def CreateProcess(*args): 
    startupinfo = args[-1] 

    # If we are passed a LoginSTARTUPINFO, that means we need to use 
    # CreateProcessAsUser instead of the CreateProcess in subprocess 
    if isinstance(startupinfo, LoginSTARTUPINFO): 
     # Gets the actual win32 STARTUPINFO object from LoginSTARTUPINFO 
     win32startupinfo = startupinfo.win32startupinfo 

     mkprocargs = args[:-1] + (win32startupinfo,) 

     login, domain, password = startupinfo.credentials 

     # Get a user handle from the credentials 
     userhandle = win32security.LogonUser(login, domain, password, 
      win32con.LOGON32_LOGON_INTERACTIVE, 
      win32con.LOGON32_PROVIDER_DEFAULT) 

     try: 
      # Return the pipes from CreateProcessAsUser 
      return win32process.CreateProcessAsUser(userhandle, *mkprocargs) 
     finally: 
      # Close the userhandle before throwing whatever error arises 
      userhandle.Close() 

    return win32process.CreateProcess(*args) 

# Overrides the CreateProcess module of subprocess with ours. CreateProcess 
# will automatically act like the original CreateProcess when it is not passed 
# a LoginSTARTUPINFO object. 
STARTUPINFO = subprocess.STARTUPINFO = win32process.STARTUPINFO 
subprocess._subprocess.CreateProcess = CreateProcess 

Le code suivant lance cmd.exe en tant qu'utilisateur username:

>>> import subprocesswin32 as subprocess 
>>> sysuser = LoginSTARTUPINFO("username", "pswd123", "machine") 
>>> stdout, stderr = subprocess.Popen("cmd.exe", stdout=subprocess.PIPE, 
...  startupinfo=sysuser).communicate() 
+0

Cela a été édité dans la question par l'OP - déplacé vers une réponse CW. –

+0

le lien est 404 – jfs