私はWindows VistaとPython 2.7.2を使用していますが、答えはPythonである必要はありません。
ですから、 `dir
‘のようなコマンドラインプログラムでは、標準プロセスのstdin/stdout(Pythonを使って)を起動して対話することができます。
– しかしながら –
既存のcmd.exeウィンドウから実行されたとしても、新しいハンドルを使ってWindows(cursesではなく)上に新しいコンソールウィンドウを作成するのが好きです。
(奇妙なのは、それはVLCの “リモートコントロール”インターフェースです)。どちらの方法もありますか?
- プロセス製コンソールのstdin/outのハンドルを取得する。または
- 古いシェルの中で新しいシェルを動かす(bashの中からbashを起動するような)?
それでは、サブプロセスのコードをハックすることができるように、Windowsで新しいコンソールを設定し、入出力を転送する方法はありますか?
編集: 私。
>>> p = Popen(args=['vlc','-I','rc'],stdin=PIPE,stdout=PIPE)
# [New console appears with text, asking for commands]
>>> p.stdin.write("quitrn")
Traceback:
File "", line 1, in
IOError: [Errno 22] Invalid argument
>>> p.stdout.readline()
''
>>> p.stdout.readline()
''
# [...]
しかし、新しいコンソールウィンドウには、キーボード入力も受け付けていません。
一方、通常:
>>> p = Popen(args=['cmd'],stdin=PIPE,stdout=PIPE)
>>> p.stdin.write("dirrn")
>>> p.stdin.flush()
>>> p.stdout.readline() #Don't just do this IRL, may block.
'Microsoft Windows [Version...
私はrcインタフェースがWindows上でパイプ接続されたstdin/stdoutで動作するようにはなっていません。
通信
するか、 stdin
に直接書き込むすべての試みで
IOError
を取得します。 rcインタフェースをLinux上でスクリプト化できるようにするオプション
- 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
オプションを使用して調理したちょっとしたデモがあります。また、 - 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'SoftwareVideoLANVLC'
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)