StandardOutput/StandardError 抓不到的輸出訊息
1 |
用 C#/PowerShell 呼叫 .exe 程式,透過 StandardOuput、StandardError 讀取程式輸出算是 .NET 基本技巧 (參考:命令列工具的 stdout, stderr 輸出與 .NET 整合應用),理論上要整合各式 CLI 程式都不成問題。今天踢到一塊鐵板,才知自己見識淺薄。
我想用 PowerShell 呼叫 gpg --full-gen-key
簡化金鑰產生作業,有段程式寫法如下:
$p = New-Object System.Diagnostics.Process
$p.StartInfo.FileName = "gpg.exe"
$p.StartInfo.Arguments = "--full-gen-key"
$p.StartInfo.UseShellExecute = $false
$p.StartInfo.RedirectStandardOutput = $true
$p.StartInfo.RedirectStandardInput = $true
$p.StartInfo.RedirectStandardError = $true
$p.Start() | Out-Null
$p.WaitForExit()
既已設定 RedirectStandardOutput、RedirectStandardError,理論上不管正常或錯誤輸出應都被導向至 StreamReader 等我讀取,殊不知 gpg 還是能列出金鑰型別選項,登楞!
用 CMD 導向指令 gpg --full-gen-key >msg.txt 2>&1
也能印證這點:
爬文查到有人問過類似問題,由網友回覆學到新東西,除了 stdout, stderr 外,還有一個終端機傳輸通道 - /dev/tty
(相當於 Windows 世界 CON:),這塊不支援導向處理。
寫一小段 C 來驗證:(參考:Windows VSCode C/C++ 開發環境安裝指令懶人包)
#include <stdio.h>
#include <stdlib.h>
int main() {
printf("This is a message to stdout\n");
fprintf(stderr, "This is a message to stderr\n");
// FILE* fout = fopen("/dev/tty", "w"); for Linux
FILE* fout = fopen("con:", "w");
fprintf(fout, "This is a message to /dev/tty\n");
fclose(fout);
return EXIT_SUCCESS;
}
在 Linux 端驗證,結果相同:
爬文跟問 ChatGPT 的結論是 /dev/tty 無法被導向,可能要搞個終端機模擬環境去攔截,工程大了點,決定繞道。
This ariticle introduce the concept of /dev/tty and why it cannot be redirected.
Comments
# by Ben
原來如此,幾個禮拜前用c# redirect git的 ouput和error也遇到這樣的問題