From 9f37995efcfa966291224a3043f72f724bd4bbb7 Mon Sep 17 00:00:00 2001 From: Rich Siegel Date: Thu, 1 Oct 2015 21:45:48 -0400 Subject: [PATCH] (GH-60) fix upgrade/installation Filestream errors on PSv2 Powershell version 2, has several issues in handling output redirection This is best documented here: https://connect.microsoft.com/PowerShell/feedback/details/587165/ powershell-double-redirection-problem Another obscure bug that occurs in powershell is here. https://connect.microsoft.com/PowerShell/feedback/details/371321/ benign-errors-for-missing-closing-are-left-in-the-error-variable These 2 issues are compounded in the provider, because the benign error sent to $error, then triggers the double redirection issue within puppet. This will automatically fail the resource. This patch is confined to Powershell v2 (Win2008r2/Win7) and essentially captures the output from running chocolateyInstall.ps1 via a variable. We can now see the errors that are thrown instead of the FileStream errors in a log stored here: $env:TEMP\chocoError.log While this may cause a false positive success to be returned to puppet, IMHO this is better than a false failure, based on upstream legacy bugs to be returned, particularly because of the transparency around the $error content. This fix leaves the existing logic intact for Powershell versions greater than 2 as I have not observed this behavior on them. Additionally write-host calls were switched to write-output as a best practice to avoid observed Filestream errors within this edge case. The recommendation to avoid this scenario altogether on Win2008r2 is to install .NET 4.5 and then WMF 4.0, or use Win2012+ --- templates/InstallChocolatey.ps1.erb | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/templates/InstallChocolatey.ps1.erb b/templates/InstallChocolatey.ps1.erb index b4966fb1..af31423d 100644 --- a/templates/InstallChocolatey.ps1.erb +++ b/templates/InstallChocolatey.ps1.erb @@ -30,13 +30,14 @@ $chocTempDir = Join-Path $env:TEMP "chocolatey" $tempDir = Join-Path $chocTempDir "chocInstall" if (![System.IO.Directory]::Exists($tempDir)) {[System.IO.Directory]::CreateDirectory($tempDir)} $file = Join-Path $tempDir "chocolatey.zip" +$chocErrorLog = Join-Path $tempDir "chocError.log" function Download-File { param ( [string]$url, [string]$file ) - Write-Host "Downloading $url to $file" + Write-Output "Downloading $url to $file" $downloader = new-object System.Net.WebClient $downloader.Proxy.Credentials=[System.Net.CredentialCache]::DefaultNetworkCredentials; $downloader.DownloadFile($url, $file) @@ -47,13 +48,13 @@ Download-File $url $file if ($unzipMethod -eq '7zip') { # download 7zip - Write-Host "Download 7Zip commandline tool" + Write-Output "Download 7Zip commandline tool" $7zaExe = Join-Path $tempDir '7za.exe' Download-File 'https://chocolatey.org/7za.exe' "$7zaExe" # unzip the package - Write-Host "Extracting $file to $tempDir..." + Write-Output "Extracting $file to $tempDir..." Start-Process "$7zaExe" -ArgumentList "x -o`"$tempDir`" -y `"$file`"" -Wait -NoNewWindow } else { $shellApplication = new-object -com shell.application @@ -63,13 +64,21 @@ if ($unzipMethod -eq '7zip') { } # call chocolatey install -Write-Host "Installing chocolatey on this machine" +Write-Output "Installing chocolatey on this machine" $toolsFolder = Join-Path $tempDir "tools" $chocInstallPS1 = Join-Path $toolsFolder "chocolateyInstall.ps1" -& $chocInstallPS1 +if ($PSVersionTable.psversion.Major -gt 2) { + & $chocInstallPS1 +} +else { + $output = Invoke-Expression $chocInstallPS1 + $output + write-output "Any errors that occured during install or upgrade are logged here: $chocoErrorLog" + $error | out-file $chocErrorLog +} -Write-Host 'Ensuring chocolatey commands are on the path' +Write-Output 'Ensuring chocolatey commands are on the path' $chocInstallVariableName = "ChocolateyInstall" $chocoPath = [Environment]::GetEnvironmentVariable($chocInstallVariableName, [System.EnvironmentVariableTarget]::User) if ($chocoPath -eq $null -or $chocoPath -eq '') { @@ -82,7 +91,7 @@ if ($($env:Path).ToLower().Contains($($chocoBinPath).ToLower()) -eq $false) { $env:Path = [Environment]::GetEnvironmentVariable('Path',[System.EnvironmentVariableTarget]::Machine); } -Write-Host 'Ensuring chocolatey.nupkg is in the lib folder' +Write-Output 'Ensuring chocolatey.nupkg is in the lib folder' $chocoPkgDir = Join-Path $chocoPath 'lib\chocolatey' $nupkg = Join-Path $chocoPkgDir 'chocolatey.nupkg' if (![System.IO.Directory]::Exists($chocoPkgDir)) { [System.IO.Directory]::CreateDirectory($chocoPkgDir); }