Windows: sous-processus créant une nouvelle fenêtre de console, perdant stdin / out

J’utilise Windows Vista et Python 2.7.2, mais les réponses ne doivent pas nécessairement être en Python.

Je peux donc démarrer et interagir normalement avec un sous-processus stdin / stdout (en utilisant python), pour des programmes en ligne de commande tels que `dir ‘.
– toutefois –
le programme que je veux maintenant appeler aime créer une nouvelle fenêtre de console sur Windows (pas de curses), avec de nouveaux descripteurs, même s’il est exécuté depuis une fenêtre cmd.exe préexistante. (Odd, car c’est l’interface “remote control” de VLC). Y a-t-il un moyen de:

  1. obtenir les poignées pour le stdin / out de la console créée par le processus; ou
  2. faire fonctionner le nouveau shell dans l’ancien (comme invoquer bash depuis bash)?

À défaut, pour que je puisse pirater le code des sous-processus, comment une nouvelle console pourrait-elle être configurée dans Windows et dans / sortie transférée?

Edit: Ie

>>> p = Popen(args=['vlc','-I','rc'],stdin=PIPE,stdout=PIPE) # [New console appears with text, asking for commands] >>> p.stdin.write("quit\r\n") Traceback: File "", line 1, in  IOError: [Errno 22] Invalid argument >>> p.stdout.readline() '' >>> p.stdout.readline() '' # [...] 

Mais la nouvelle fenêtre de la console ne permet pas non plus la saisie au clavier.

Considérant que normalement:

 >>> p = Popen(args=['cmd'],stdin=PIPE,stdout=PIPE) >>> p.stdin.write("dir\r\n") >>> p.stdin.flush() >>> p.stdout.readline() #Don't just do this IRL, may block. 'Microsoft Windows [Version... 

Je n’ai pas eu l’interface rc pour travailler avec un stdin / stdout canalisé sur Windows; IOError à toutes les tentatives de communicate ou d’écriture directe sur stdin . Il y a une option --rc-fake-tty qui permet à l’interface rc d’être scriptée sur Linux, mais elle n’est pas disponible dans Windows – du moins pas dans ma version un peu désuète de VLC (1.1.4). L’utilisation de l’interface socket, par contre, semble fonctionner correctement.

La structure affectée à l’option startupinfo – et utilisée par la fonction Win32 CreateProcess – peut être configurée pour masquer une fenêtre de processus. Cependant, pour la console RLC VLC, je pense qu’il est plus simple d’utiliser l’option --rc-quiet existante. En général, voici comment configurer startupinfo pour masquer une fenêtre de processus:

 startupinfo = subprocess.STARTUPINFO() startupinfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW subprocess.Popen(cmd, startupinfo=startupinfo) 

Juste pour être complet – dans le cas où l’utilisation de pipes échoue également sur votre système – voici une petite démonstration que j’ai préparée en utilisant l’option --rc-host pour communiquer en utilisant un socket. Il utilise également --rc-quiet pour masquer la console. Cela imprime simplement l’aide et se ferme. Je n’ai rien testé d’autre. J’ai vérifié qu’il fonctionne dans les versions Python 2.7.2 et 3.2.2. (Je sais que vous ne l’avez pas demandé, mais peut-être que cela vous sera néanmoins utile.)

 import socket import subprocess from select import select try: import winreg except ImportError: import _winreg as winreg def _get_vlc_path(): views = [(winreg.HKEY_CURRENT_USER, 0), (winreg.HKEY_LOCAL_MACHINE, winreg.KEY_WOW64_64KEY), (winreg.HKEY_LOCAL_MACHINE, winreg.KEY_WOW64_32KEY)] subkey = r'Software\VideoLAN\VLC' access = winreg.KEY_QUERY_VALUE for hroot, flag in views: try: with winreg.OpenKey(hroot, subkey, 0, access | flag) as hkey: value, type_id = winreg.QueryValueEx(hkey, None) if type_id == winreg.REG_SZ: return value except WindowsError: pass raise SystemExit("Error: VLC not found.") g_vlc_path = _get_vlc_path() def send_command(sock, cmd, get_result=False): try: cmd = (cmd + '\n').encode('ascii') except AtsortingbuteError: cmd += b'\n' sent = total = sock.send(cmd) while total < len(cmd): sent = sock.send(cmd[total:]) if sent == 0: raise socket.error('Socket connection broken.') total += sent if get_result: return receive_result(sock) def receive_result(sock): data = bytearray() sock.setblocking(0) while select([sock], [], [], 1.0)[0]: chunk = sock.recv(1024) if chunk == b'': raise socket.error('Socket connection broken.') data.extend(chunk) sock.setblocking(1) return data.decode('utf-8') def main(address, port): import time rc_host = '{0}:{1}'.format(address, port) vlc = subprocess.Popen([g_vlc_path, '-I', 'rc', '--rc-host', rc_host, '--rc-quiet']) sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) try: sock.connect((address, port)) help_msg = send_command(sock, 'help', True) print(help_msg) send_command(sock, 'quit') except socket.error as e: exit("Error: " + e.args[0]) finally: sock.close() time.sleep(0.5) if vlc.poll() is None: vlc.terminate() if __name__ == '__main__': main('localhost', 12345) 

En référence à la surveillance du stdOut qui apparaît dans la nouvelle fenêtre de la console générée.

Voici une autre question / réponse qui résout le problème.

En résumé (comme répondu par Adam MW ):

  • Supprimez la nouvelle console générée en lançant vlc en mode silencieux --intf=dummy --dummy-quiet ou --intf=rc --rc-quiet .
  • Surveiller stdErr du processus lancé

Remarque: En ce qui concerne les commandes stdIn pour l’interface rc, la solution --rc-host est décrite par la réponse d’eryksun