我正在使用Windows Vista和Python 2.7.2,但答案不一定是Python。
因此,对于命令行程序,例如`dir',我可以正常启动并与子进程stdin / stdout(使用python)进行交互。
- 但是 -
我现在想调用的程序喜欢在Windows(而不是curses)上创建一个新的控制台窗口,使用新句柄,即使从预先存在的cmd.exe窗口运行也是如此。 (奇怪,因为它是VLC的“远程控制”界面。)有没有办法:
如果失败了,那么我可以破解子进程的代码,如何在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 :(得分:1)
我还没有让rc接口在Windows上使用管道stdin / stdout;我在IOError
的所有尝试中获得communicate
或直接写入stdin
。有一个选项--rc-fake-tty
可以让rc接口在Linux上编写脚本,但它在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
选项使用套接字进行通信的一个小实验。它还使用--rc-quiet
来隐藏控制台。这只是打印帮助和退出。我没有测试任何其他东西。我检查它在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)
答案 1 :(得分:0)
参考监视出现在新的Spawned控制台窗口中的stdOut。
这是解决问题的another question/answer。
总结(由Adam M-W回答):
--intf=dummy --dummy-quiet
或--intf=rc --rc-quiet
启动vlc来抑制新生成的控制台。注意:对于rc接口的stdIn命令,eryksun´s answer
描述了--rc-host
解决方案