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:
À 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 ):
--intf=dummy --dummy-quiet
ou --intf=rc --rc-quiet
. 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