From 93797b36535a040e6c695e9058f93758f3862346 Mon Sep 17 00:00:00 2001 From: Niklas Guertler Date: Mon, 8 Feb 2016 17:10:56 +0100 Subject: [PATCH] (GH-616) Capture 7z's stdout in Get-ChocolateyUnzip Sometimes, Install-ChocolateyZipPackage and Get-ChocolateyUnzip capture files that don't belong to the package, record them in the Install.zip.txt file, and cause them to be removed upon uninstallation by UnInstall-ChocolateyZipPackage. This fix uses 7z's standard output instead to determine which files belong to the package. This also avoids scanning possibly large directory trees. --- .../helpers/functions/Get-ChocolateyUnzip.ps1 | 56 +++++++++++-------- 1 file changed, 34 insertions(+), 22 deletions(-) diff --git a/src/chocolatey.resources/helpers/functions/Get-ChocolateyUnzip.ps1 b/src/chocolatey.resources/helpers/functions/Get-ChocolateyUnzip.ps1 index 49f47c01fe..d387b07232 100644 --- a/src/chocolatey.resources/helpers/functions/Get-ChocolateyUnzip.ps1 +++ b/src/chocolatey.resources/helpers/functions/Get-ChocolateyUnzip.ps1 @@ -91,32 +91,44 @@ param( $destination32 = $destination } - $exitCode = -1 - $unzipOps = { - param($7zip, $destination, $fileFullPath, [ref]$exitCodeRef) - $params = "x -aoa -o`"$destination`" -y `"$fileFullPath`"" - Write-Debug "Executing command ['$7zip' $params]" - $process = New-Object System.Diagnostics.Process - $process.StartInfo = new-object System.Diagnostics.ProcessStartInfo($7zip, $params) - $process.StartInfo.UseShellExecute = $false - $process.StartInfo.WindowStyle = [System.Diagnostics.ProcessWindowStyle]::Hidden - + # Make structures used by .NET for starting the 7z process + + # 7z command line + $params = "x -aoa -o`"$destination`" -y `"$fileFullPath`"" + $process = New-Object System.Diagnostics.Process + $process.StartInfo = new-object System.Diagnostics.ProcessStartInfo($7zip, $params) + # Required for stdout redirect + $process.StartInfo.UseShellExecute = $false + $process.StartInfo.WindowStyle = [System.Diagnostics.ProcessWindowStyle]::Hidden + + Write-Debug "Executing command ['$7zip' $params]" + if ($zipExtractLogFullPath) { + # Redirect stdout for processing by choco + $process.StartInfo.RedirectStandardOutput = $true $process.Start() | Out-Null - $process.WaitForExit() - $processExitCode = $process.ExitCode - $process.Dispose() - Write-Debug "Command ['$7zip' $params] exited with `'$processExitCode`'." - - $exitCodeRef.Value = $processExitCode - } - if ($zipExtractLogFullPath) { - Write-Debug "wrapping 7za invocation with Write-FileUpdateLog" - Write-FileUpdateLog -logFilePath $zipExtractLogFullPath -locationToMonitor $destination -scriptToRun $unzipOps -argumentList $7zip,$destination32,$fileFullPath32,([ref]$exitCode) + # Read each line from 7z's stdout synchroneously (ReadLine blocks). + # Since stderr is not redirected, it gets automatically printed to the console, avoiding deadlocks. + while(($process.StandardOutput -ne $null) -and (($line = $process.StandardOutput.ReadLine()) -ne $null)) { + if($line.StartsWith("Extracting")) { + # This is a line indicating an extracted file + $file = $destination + "\" + $line.Substring(12) + # Save the filename + Add-Content $zipExtractLogFullPath $file + } + # Print the line, such that it looks as if stdout was not redirected + Write-Debug $line + } } else { - Write-Debug "calling 7za directly" - Invoke-Command $unzipOps -ArgumentList $7zip,$destination32,$fileFullPath32,([ref]$exitCode) + # If we don't want to capture the file list, just execute 7z without stdout redirection + $process.Start() | Out-Null } + + # Wait for 7z to finish. Even if 7z has closed its stdout, and all lines have been read, the process might not have quit yet. + $process.WaitForExit() + $exitCode = $process.ExitCode + $process.Dispose() + Write-Debug "Command ['$7zip' $params] exited with `'$exitCode`'." Write-Debug "7za exit code: $exitCode" switch ($exitCode) {