Powershell能从stdin读取代码吗?

时间:2014-02-17 16:05:52

标签: python powershell

我正在尝试从Python运行Powershell子流程。我需要将Python中的Powershell代码发送到子进程。我到目前为止:

import subprocess
import time

args = ["powershell", "-NoProfile", "-InputFormat None", "-NonInteractive"]

startTime = time.time()
process = subprocess.Popen(args, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)

process.stdin.write("Write-Host 'FINISHED';".encode("utf-8"))

result = ''
while 'FINISHED' not in result:
    result += process.stdout.read(32).decode('utf-8')
    if time.time() > startTime + 5:
        raise TimeoutError(result)
print(result)

这次超时,因为没有任何东西被写入stdout。我认为Write-Host cmdlet永远不会被执行。即使是简单的bash / Cygwin代码echo "Write-Host 'FINISHED';" | powershell似乎也无法完成这项任务。

为了进行比较,使用-Command标志发送代码块可以正常工作。

如何说服Powershell运行我发送给stdin的代码?

2 个答案:

答案 0 :(得分:3)

您可以考虑以下几点:

  1. 在您为其提供应执行的脚本文件的模式下调用PowerShell。在调用子进程之前编写此脚本文件。使用PowerShell的-File <FilePath>参数(参见docs

  2. 如果您真的想使用stdin技术,可能会在命令后丢失换行符。如果这没有帮助,您可能需要发送另一个控制字符,告诉PowerShell达到输入EOF。您肯定需要查阅PowerShell文档以了解如何在stdin上“终止”命令。你绝对需要的一件事是-Command -论点:The value of Command can be "-", a string. or a script block. If the value of Command is "-", the command text is read from standard input.你可能也想看看这个小小的黑客:https://stackoverflow.com/a/13877874/145400

  3. 如果您只想执行一个命令,可以使用out, err = subprocess.communicate(in)

  4. 简化代码

答案 1 :(得分:2)

我遇到了类似的任务,但我能够解决它。

首先是我的示例代码:

import subprocess

args = ["powershell.exe", "-Command", r"-"]
process = subprocess.Popen(args, stdin = subprocess.PIPE, stdout =   subprocess.PIPE)

process.stdin.write(b"$data = Get-ChildItem C:\\temp\r\n")
process.stdin.write(b"Write-Host 'Finished 1st command'\r\n")
process.stdin.write(b"$data | Export-Clixml -Path c:\\temp\state.xml\r\n")
process.stdin.write(b"Write-Host 'Finished 2nd command'\r\n")

output = process.communicate()[0]

print(output.decode("utf-8"))
print("done")

主要问题是正确的参数列表 args 。需要使用 -Command -flag启动powershell,然后按Jan-Philipp所示的“ - ”启动。

另一个谜团是执行这些东西所需的行尾字符。 \ r \ n 效果很好。

获取Powershell的输出仍然是一个问题。但如果你不关心实时,你可以通过调用

完成所有执行后收集输出
output = process.communicate()[0]

但是,活跃的Powershell将在之后终止。