2014-02-17 57 views
4

我試圖從Python運行Powershell子流程。我需要將Python的Powershell代碼發送給子進程。我有這麼多:Powershell可以從stdin中讀取代碼嗎?

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) 

這個超時,因爲沒有任何東西會寫入標準輸出。我認爲Write-Host cmdlet永遠不會被執行。即使是簡單的bash/Cygwin代碼echo "Write-Host 'FINISHED';" | powershell似乎也沒有完成這項工作。

用於比較,使用-Command標誌發送代碼塊可正常工作。

我該如何說服Powershell運行我發送給stdin的代碼?

回答

2

有幾件事情你可以考慮:

  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.您可能也想看看這個小黑客:使用out, err = subprocess.communicate(in)

https://stackoverflow.com/a/13877874/145400

  • 如果你只是想執行一個命令,就可以簡化代碼

  • +0

    我無法使用文件或「溝通」,因爲需要將一些代碼塊發送到_single_進程。這兩個選項都會導致子進程退出。遺憾的是,分叉多個Powershell流程不是一種選擇。 –

    +1

    絕對有可能將來自stdin的輸入提供給PowerShell。我添加了一些更多的信息(關於'-Command -')。這應該讓你開始。 –

    +0

    所以不幸的是,它看起來像Powershell不執行你輸入的代碼,直到它收到EOF。所以我想要做的是不使用某種消息傳遞,這對我的應用來說太複雜了。哦:( –

    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。需要使用- 命令 -flag啓動PowerShell,然後按照Jan-Philipp的指示啓動「 - 」。

    另一個謎團是獲得執行的內容所需的行尾字符。 \ r \ n工作得很好。

    獲取Powershell的輸出仍然是一個問題。但是,如果你不關心實時的,你可以通過調用

    output = process.communicate()[0] 
    

    但是收集整理所有執行後的輸出,主動PowerShell的將在後面終止。