使用 stdout=subprocess.PIPE
会阻止输出到控制台,但不会捕获任何内容。
>>> import subprocess
>>> proc = subprocess.Popen(['C:\\Users\\me\\program.exe'])
>>> ERROR: please provide an argument
// TRUNCATED USAGE OUTPUT
proc.wait()
0
>>> proc = subprocess.Popen([''C:\\Users\\me\\program.exe''], stdout=subprocess.PIPE)
>>> proc.communicate()
('', None)
我已经尝试了 stackoverflow 上可用的所有组合。
shell=True
没有用。生成子 cmd
没有用。 subprocess.check_output
什么也没有捕获。我很高兴在评论中重试这些命令中的任何一个。我猜这与程序附加到 shell 有关。
这是程序用于输出的程序集(
mcall
只是一个将内存对齐到 16 位的宏)。我包含这个的原因是以防 GetStdHandle
影响事情。console_write PROC
; rcx MSG
; rdx LEN
prologue
push rcx
push rdx
xor rcx, rcx
mov ecx, [stdout]
mcall GetStdHandle
mov rcx, rax
xor rdx, rdx
pop r8 ; len
pop rdx ; msg
push 0
mov r9, rsp
push 0
mcall WriteConsoleA
pop rcx
pop rcx
epilogue
console_write ENDP
我被这个难住了。我已经在 Linux 上做过很多次了。我只是对 Windows 内部了解不够,无法解决这个问题。谢谢!
编辑:我尝试过的其他内容:
管理员(也使用 STDERR 捕获)
C:\Windows\system32>C:\Python27\python.exe
Python 2.7.14 (v2.7.14:84471935ed, Sep 16 2017, 20:19:30) [MSC v.1500 32 bit (Intel)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import subprocess
>>> proc = subprocess.Popen(['C:\\Users\\me\\program.exe'], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
>>> proc.communicate()
('', '')
STDOUT 文件重定向
>>> import os
>>> os.system('C:\\Users\\me\\program.exe > out.txt')
0
>>> f = open('out.txt', 'r')
>>> f.read()
''
STDERR 文件重定向
>>> import os
>>> os.system('C:\\Users\\me\\program.exe 2>out.txt')
ERROR: please provide an argument
// TRUNCATED USAGE OUTPUT
0
>>> open('out.txt', 'r').read()
''
命令行捕获失败(禁止进入 cmd 的输出,但没有捕获任何内容)
program.exe > out.txt
最佳答案
一位同事指出了这个问题。结果证明 WriteConsole
不能重定向到文件,它只能与控制台句柄一起使用。 [1] [2]
这个 StackOverflow answer 给出了如何解决它的概述。如果其他人有这个问题,我已经在 Python 中实现了它。
import win32console
import subprocess
import msvcrt
import os
ccsb = win32console.CreateConsoleScreenBuffer()
fd = msvcrt.open_osfhandle(ccsb, os.O_APPEND)
proc = subprocess.Popen(['C:\\Users\\me\\program.exe'], stdout=fd)
proc.wait()
ccsb.ReadConsoleOutputCharacter(100, win32console.PyCOORDType(0,0)) # reads 100 characters from the first line
对我来说更好的解决方案是使用相同的
WriteConsoleA
将 WriteFile
更改为 StdHandle
。console_write PROC
; rcx MSG
; rdx LEN
prologue
push rcx
push rdx
xor rcx, rcx
mov ecx, [stdout]
mcall GetStdHandle
mov rcx, rax
; Write File
pop r8 ; len
pop rdx ; msg
; unalign for odd number of pushed args
mov rbx, rsp
sub rbx, 8
and rbx, 0Fh
sub rsp, rbx
; args
mov rcx, rax ; handle
xor r9, r9
push 0 ; 1 arg (ununaligns)
sub rsp, 20h ; shadow
call WriteFile
add rsp, 28h ; shadow + arg
add rsp, rbx ; realign
epilogue
console_write ENDP