GitHub からいくつかのリポジトリをダウンロードするスクリプトを書いています。リポジトリをダウンロードするコマンドは次のとおりです。
git clone "$RepositoryUrl" "$localRepoDirectory"
このコマンドを実行すると、表示したいコンソール ウィンドウに進行状況の情報が表示されます。
問題は、ダウンロード中にエラーが発生したかどうかも検出できるようにしたいことです。さまざまなストリームのリダイレクトについて説明しているこの投稿を見つけたので、試しました:
(git clone "$RepositoryUrl" "$localRepoDirectory") 2> $errorLogFilePath
これにより、stderr からファイルにエラーがパイプされますが、コンソールに進行状況の情報が表示されなくなります。
次のように Tee-Object を使用できます。
(git clone "$RepositoryUrl" "$localRepoDirectory") | Tee-Object -FilePath $errorLogFilePath
そして、私はまだ素晴らしい進行状況の出力を取得しますが、これは stderr ではなく stdout をファイルにパイプします。エラーの検出のみに関心があります。
ファイルまたは (できれば) 変数で発生したエラーを保存しながら、進行状況の情報をコンソール ウィンドウにパイプする方法はありますか? この投稿で説明されているように、さまざまなストリームを他のストリームにリダイレクトすることに答えがあるのではないかと感じていますが、よくわかりません。
========更新=======
git.exe が一般的な実行可能ファイルと異なるかどうかはわかりませんが、さらにテストを行ったところ、次のような結果が得られました。
$output = (git clone "$RepositoryUrl" "$localRepoDirectory")
$output には、コマンドが正常に完了したかエラーが発生したかに関係なく、常に「'[localRepoDirectory]' へのクローン作成中...」というテキストが含まれます。また、これを行うと、進行状況の情報が引き続きコンソールに書き込まれます。これは、進行状況情報が stdout 経由ではなく、他のストリームによって書き込まれていると思いますか?
エラーが発生した場合、エラーはコンソールに書き込まれますが、エラーの場合は典型的な赤、警告の場合は黄色ではなく、通常の白い前景色で表示されます。これがコマンドレット関数内から呼び出され、コマンドがエラーで失敗した場合、関数の -ErrorVariable (または -WarningVariable) パラメーターを介してエラーは返されません (ただし、独自の Write-Error を実行すると、-ErrorVariable を介して返されます) )。これにより、git.exe は stderr に書き込まないと思いますが、そうすると:
(git clone "$RepositoryUrl" "$localRepoDirectory") 2> $errorLogFilePath
エラーメッセージはファイルに書き込まれるので、stderrに書き込むと思います。だから今、私は混乱しています...
========更新2 =======
そのため、Byron の助けを借りて、新しいプロセスを使用してさらにいくつかの解決策を試しましたが、まだ必要なものを得ることができません。新しいプロセスを使用すると、コンソールに進捗状況が書き込まれません。
私が試した 3 つの新しい方法は、どちらも次のコードを共通して使用しています。
$process = New-Object System.Diagnostics.Process
$process.StartInfo.Arguments = "clone ""$RepositoryUrl"" ""$localRepoDirectory"""
$process.StartInfo.UseShellExecute = $false
$process.StartInfo.RedirectStandardOutput = $true
$process.StartInfo.RedirectStandardError = $true
$process.StartInfo.CreateNoWindow = $true
$process.StartInfo.WorkingDirectory = $WORKING_DIRECTORY
$process.StartInfo.FileName = "git"
方法 1 - 新しいプロセスで実行し、その後出力を読み取ります。
$process.Start()
$process.WaitForExit()
Write-Host Output - $process.StandardOutput.ReadToEnd()
Write-Host Errors - $process.StandardError.ReadToEnd()
方法 2 - 出力を同期的に取得する:
$process.Start()
while (!$process.HasExited)
{
Write-Host Output - $process.StandardOutput.ReadToEnd()
Write-Host Error Output - $process.StandardError.ReadToEnd()
Start-Sleep -Seconds 1
}
これは、プロセスの実行中に出力を書き込むように見えますが、プロセスが終了するまで何も書き込みません。
方法 3 - 出力を非同期的に取得する:
Register-ObjectEvent -InputObject $process -EventName "OutputDataReceived" -Action {Write-Host Output Data - $args[1].Data }
Register-ObjectEvent -InputObject $process -EventName "ErrorDataReceived" -Action { Write-Host Error Data - $args[1].Data }
$process.Start()
$process.BeginOutputReadLine()
$process.BeginErrorReadLine()
while (!$process.HasExited)
{
Start-Sleep -Seconds 1
}
これは、プロセスが動作している間にデータを出力しますが、それでも良い進行状況情報は表示されません:(