diff --git a/scripts/run-clean-scratch-iterations.ps1 b/scripts/run-clean-scratch-iterations.ps1 index f00757933..52de10b41 100644 --- a/scripts/run-clean-scratch-iterations.ps1 +++ b/scripts/run-clean-scratch-iterations.ps1 @@ -67,6 +67,16 @@ function Format-ProcessArgument { return '"' + ($Value -replace '(\\*)"', '$1$1\"' -replace '(\\+)$', '$1$1') + '"' } +function ConvertTo-PowerShellLiteral { + param( + [Parameter(Mandatory = $true)] + [AllowEmptyString()] + [string]$Value + ) + + return "'" + ($Value -replace "'", "''") + "'" +} + function Invoke-External { param( [Parameter(Mandatory = $true)] @@ -80,6 +90,7 @@ function Invoke-External { Push-Location $WorkingDirectory $stdoutPath = New-LogCapturePath -Suffix '.stdout.log' $stderrPath = New-LogCapturePath -Suffix '.stderr.log' + $wrapperPath = New-LogCapturePath -Suffix '.invoke.ps1' try { $resolvedFilePath = $FilePath if (Test-Path $FilePath) { @@ -88,21 +99,32 @@ function Invoke-External { $startFilePath = $resolvedFilePath $startArgumentList = @($ArgumentList) + $powershellPath = (Get-Command powershell.exe -ErrorAction Stop).Source if ([System.IO.Path]::GetExtension($resolvedFilePath).Equals('.ps1', [System.StringComparison]::OrdinalIgnoreCase)) { - $powershellPath = (Get-Command powershell.exe -ErrorAction Stop).Source $startFilePath = $powershellPath $startArgumentList = @('-NoLogo', '-NoProfile', '-ExecutionPolicy', 'Bypass', '-File', $resolvedFilePath) + @($ArgumentList) } - $formattedArgumentList = @($startArgumentList | ForEach-Object { Format-ProcessArgument -Value $_ }) + $invocationExpression = '& ' + (ConvertTo-PowerShellLiteral -Value $startFilePath) + if ($startArgumentList.Count -gt 0) { + $invocationExpression += ' ' + (($startArgumentList | ForEach-Object { ConvertTo-PowerShellLiteral -Value $_ }) -join ' ') + } + + $wrapperContent = @( + '$ErrorActionPreference = ''Stop''' + "$invocationExpression 1> $(ConvertTo-PowerShellLiteral -Value $stdoutPath) 2> $(ConvertTo-PowerShellLiteral -Value $stderrPath)" + 'exit $LASTEXITCODE' + '' + ) + Set-Content -Path $wrapperPath -Value $wrapperContent -Encoding UTF8 + + $formattedArgumentList = @(@('-NoLogo', '-NoProfile', '-ExecutionPolicy', 'Bypass', '-File', $wrapperPath) | ForEach-Object { Format-ProcessArgument -Value $_ }) $process = Start-Process ` - -FilePath $startFilePath ` + -FilePath $powershellPath ` -ArgumentList $formattedArgumentList ` -WorkingDirectory $WorkingDirectory ` - -RedirectStandardOutput $stdoutPath ` - -RedirectStandardError $stderrPath ` -PassThru $stdoutIndex = 0 @@ -115,6 +137,8 @@ function Invoke-External { $process.Refresh() } + $process.WaitForExit() + $process.Refresh() Write-LogCaptureDelta -Path $stdoutPath -LineIndex ([ref]$stdoutIndex) Write-LogCaptureDelta -Path $stderrPath -LineIndex ([ref]$stderrIndex) @@ -123,7 +147,7 @@ function Invoke-External { } } finally { - foreach ($capturePath in @($stdoutPath, $stderrPath)) { + foreach ($capturePath in @($stdoutPath, $stderrPath, $wrapperPath)) { if (Test-Path $capturePath) { Remove-Item $capturePath -Force -ErrorAction SilentlyContinue }