2011-11-13 2 views
3

Windows Vista와 Python 2.7.2를 사용하고 있습니다. 그러나 대답은 Python 일 필요는 없습니다.WIndows : 새로운 콘솔 창을 만드는 서브 프로세스, stdin/out을 잃는

그래서`dir '과 같은 명령 행 프로그램에 대해 stdin/stdout 서브 프로세스 (파이썬 사용)를 시작하고 상호 작용할 수 있습니다.
는 - 그러나 -
내가 지금 통화 할 프로그램은 기존의 cmd.exe를 윈도우에서 실행되는 경우에도, 새로운 핸들, (저주하지 않음) Windows에서 자체에 대한 새로운 콘솔 창을 좋아한다. (이상한, VLC의 "원격 제어"인터페이스입니다.) 어떤 방법이 있습니까 :

  1. 프로세스 콘솔의 stdin/out에 대한 핸들 가져 오기; 또는
  2. bash에서 bash를 호출하는 것과 같이 이전 버전에서 새 셸을 실행하려면 어떻게해야합니까?

오류가 발생하여 서브 프로세스 코드를 해킹 할 수 있으므로 Windows에서 새 콘솔을 설정하고 출력을 전송하는 방법은 무엇입니까?

편집 : 예.

>>> 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 "<stdin>", line 1, in <module> 
IOError: [Errno 22] Invalid argument 
>>> p.stdout.readline() 
'' 
>>> p.stdout.readline() 
'' 
# [...] 

그러나 새 콘솔 창은 키보드 입력을 허용하지 않습니다.

보통 반면 :

>>> 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... 
+0

@eryksun에 의해 설명 될 때 그래, 난'VLC를 실행 해요 - 내가 rc'. – asdf

답변

1

내가 Windows에서 표준 출력 파이프 표준 입력/작동하도록 RC 인터페이스를 확보하지 못했어요; IOErrorcommunicate 번으로 시도하거나 stdin에 직접 쓸 수 있습니다. 리눅스에서 rc 인터페이스를 스크립팅 할 수있게 해주는 옵션 인 --rc-fake-tty이 있지만, Windows에서는 사용할 수 없습니다. 적어도 다소 다소 오래된 VLC (1.1.4) 버전에는 없습니다. 반면에 소켓 인터페이스를 사용하면 제대로 작동하는 것 같습니다.

startupinfo 옵션에 할당되고 Win32 CreateProcess 함수에서 사용되는 구조는 프로세스 창을 숨기도록 구성 할 수 있습니다. 그러나 VLC rc 콘솔의 경우 기존의 --rc-quiet 옵션을 사용하는 것이 더 간단하다고 생각합니다. 일반적으로, 여기에 프로세스 창을 숨길 수 startupinfo를 구성하는 방법은 다음과 같습니다 - 파이프를 사용하는 경우도 시스템에 실패 -

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

그냥 완료하기 위해 여기에 내가 --rc-host 옵션을 사용하여 조리 약간의 데모입니다 소켓을 사용하여 통신합니다. 또한 을 사용하여 콘솔을 숨 깁니다. 이것은 단지 도움말을 인쇄하고 종료합니다. 나는 다른 것을 시험하지 않았다. Python 버전 2.7.2 및 3.2.2에서 작동하는지 확인했습니다. (난 당신이 요청하지 않았다 알고,하지만 어쩌면 그것은 그럼에도 불구하고 당신에게 도움이 될 것입니다.)

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 AttributeError: 
     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) 
+0

와우, 정보 및 소켓 솔루션을 이용해 주셔서 감사합니다. 코드가 유용했습니다. 나는 그런 특별한 대답을 기대하지 않고 있었고, 나는 막 다른 길에 서 있다고 생각했다. 고맙습니다. – asdf

0

새로운 양산 콘솔 창에 표시되는 표준 출력을 모니터링을 참조.

여기는 another question/answer으로 문제를 해결합니다.(Adam M-W 응답으로) 요약

:

  • 억제 자동 모드 --intf=dummy --dummy-quiet 또는 --intf=rc --rc-quiet에 VLC를 시작하여 새로운 양산 콘솔.
  • 은 모니터 시작 프로세스의 STDERR

참고 : 표준 입력이 RC 인터페이스 명령을 들어, --rc-host 솔루션 eryksun´s answer

관련 문제