diff --git a/functions/Update-DbaInstance.ps1 b/functions/Update-DbaInstance.ps1 index 89987c48b5..cbbd2f9a2e 100644 --- a/functions/Update-DbaInstance.ps1 +++ b/functions/Update-DbaInstance.ps1 @@ -157,7 +157,7 @@ function Update-DbaInstance { [string[]]$KB, [Alias("Instance")] [string]$InstanceName, - [string[]]$Path, + [string[]]$Path = (Get-DbatoolsConfigValue -Name 'Path.SQLServerUpdates'), [switch]$Restart, [switch]$Continue, [ValidateNotNull()] @@ -286,7 +286,11 @@ function Update-DbaInstance { $activity = "Preparing to update SQL Server on $resolvedName" ## Find the current version on the computer Write-ProgressHelper -ExcludePercent -Activity $activity -StepNumber 0 -Message "Gathering all SQL Server instance versions" - $components = Get-SQLInstanceComponent -ComputerName $resolvedName -Credential $Credential + try { + $components = Get-SQLInstanceComponent -ComputerName $resolvedName -Credential $Credential + } catch { + Stop-Function -Message "Error while looking for SQL Server installations on $resolvedName" -Continue -ErrorRecord $_ + } if (!$components) { Stop-Function -Message "No SQL Server installations found on $resolvedName" -Continue } @@ -295,13 +299,17 @@ function Update-DbaInstance { if ($InstanceName) { $components = $components | Where-Object {$_.InstanceName -eq $InstanceName } } + try { + $restartNeeded = Test-PendingReboot -ComputerName $resolvedName -Credential $Credential + } catch { + Stop-Function -Message "Failed to get reboot status from $resolvedName" -Continue -ErrorRecord $_ + } + if ($restartNeeded -and (-not $Restart -or ([DbaInstanceParameter]$resolvedName).IsLocalHost)) { + #Exit the actions loop altogether - nothing can be installed here anyways + Stop-Function -Message "$resolvedName is pending a reboot. Reboot the computer before proceeding." -Continue + } $upgrades = @() :actions foreach ($currentAction in $actions) { - $restartNeeded = Test-PendingReboot -ComputerName $resolvedName - if ($restartNeeded -and (-not $Restart -or ([DbaInstanceParameter]$resolvedName).IsLocalHost)) { - #Exit the actions loop altogether - nothing can be installed here anyways - Stop-Function -Message "$resolvedName is pending a reboot. Reboot the computer before proceeding." -Continue -ContinueLabel computers - } # Attempt to configure CredSSP for the remote host when credentials are defined if ($Credential -and -not ([DbaInstanceParameter]$resolvedName).IsLocalHost -and $Authentication -eq 'Credssp') { Write-Message -Level Verbose -Message "Attempting to configure CredSSP for remote connections" @@ -350,7 +358,11 @@ function Update-DbaInstance { Path = $Path KB = $detail.KB } - $installer = Find-SqlServerUpdate @kbLookupParams + try { + $installer = Find-SqlServerUpdate @kbLookupParams + } catch { + Stop-Function -Message "Failed to enumerate files in -Path" -ErrorRecord $_ -Continue + } if ($installer) { $detail.Installer = $installer.FullName } else { @@ -455,6 +467,7 @@ function Update-DbaInstance { Write-ProgressHelper -ExcludePercent -Activity $activity -Message "Now installing update SQL$($currentAction.MajorVersion)$($currentAction.TargetLevel) from $spExtractPath" Write-Message -Level Verbose -Message "Starting installation from $spExtractPath" -FunctionName Update-DbaInstance $updateResult = Invoke-Program @execParams -Path "$spExtractPath\setup.exe" -ArgumentList @('/quiet', $instanceClause, '/IAcceptSQLServerLicenseTerms') -WorkingDirectory $spExtractPath -Fallback + $output.ExitCode = $updateResult.ExitCode if ($updateResult.Successful) { $output.Successful = $true } else { @@ -486,7 +499,13 @@ function Update-DbaInstance { } } #double check if restart is needed - if ($updateResult.ExitCode -eq 3010 -or (Test-PendingReboot -ComputerName $resolvedName)) { + try { + $restartNeeded = Test-PendingReboot -ComputerName $resolvedName -Credential $Credential + } catch { + $restartNeeded = $false + Stop-Function -Message "Failed to get reboot status from $resolvedName" -ErrorRecord $_ -FunctionName Update-DbaInstance + } + if ($updateResult.ExitCode -eq 3010 -or $restartNeeded) { if ($Restart) { # Restart the computer Write-ProgressHelper -ExcludePercent -Activity $activity -Message "Restarting computer $($computer) and waiting for it to come back online" @@ -510,7 +529,7 @@ function Update-DbaInstance { if ($installActions.Count -eq 1) { $installActions | ForEach-Object -Process $installScript | ForEach-Object -Process $outputHandler } elseif ($installActions.Count -ge 2) { - $installActions | Invoke-Parallel -ImportModules -ImportVariables -ScriptBlock $installScript -Throttle $Throttle | ForEach-Object -Process $outputHandler + $installActions | Invoke-Parallel -ImportModules -ImportVariables -ImportFunctions -ScriptBlock $installScript -Throttle $Throttle | ForEach-Object -Process $outputHandler } } } diff --git a/internal/functions/Find-SqlServerUpdate.ps1 b/internal/functions/Find-SqlServerUpdate.ps1 index 6c372e686d..6aac179b89 100644 --- a/internal/functions/Find-SqlServerUpdate.ps1 +++ b/internal/functions/Find-SqlServerUpdate.ps1 @@ -27,16 +27,14 @@ function Find-SqlServerUpdate { [string]$KB, [ValidateSet('x86', 'x64')] [string]$Architecture = 'x64', - [string[]]$Path = (Get-DbatoolsConfigValue -Name 'Path.SQLServerUpdates'), - [bool]$EnableException = $EnableException + [string[]]$Path = (Get-DbatoolsConfigValue -Name 'Path.SQLServerUpdates') ) begin { } process { if (!$Path) { - Stop-Function -Message "Path to SQL Server updates folder is not set. Consider running Set-DbatoolsConfig -Name Path.SQLServerUpdates -Value '\\path\to\updates' or specify the path in the original command" - return + throw "Path to SQL Server updates folder is not set. Consider running Set-DbatoolsConfig -Name Path.SQLServerUpdates -Value '\\path\to\updates' or specify the path in the original command" } $filter = "SQLServer$MajorVersion*-KB$KB-*$Architecture*.exe" Write-Message -Level Verbose -Message "Using filter [$filter] to check for updates in $Path" @@ -61,11 +59,6 @@ function Find-SqlServerUpdate { ErrorAction = 'Stop' Raw = $true } - try { - Invoke-CommandWithFallback @params - } catch { - Stop-Function -Message "Failed to enumerate files in $Path" -ErrorRecord $_ - return - } + Invoke-CommandWithFallback @params } } \ No newline at end of file diff --git a/internal/functions/Get-SqlInstanceComponent.ps1 b/internal/functions/Get-SqlInstanceComponent.ps1 index 9784472d5c..0758e22828 100644 --- a/internal/functions/Get-SqlInstanceComponent.ps1 +++ b/internal/functions/Get-SqlInstanceComponent.ps1 @@ -69,8 +69,7 @@ function Get-SQLInstanceComponent { [DbaInstanceParameter[]]$ComputerName = $Env:COMPUTERNAME, [ValidateSet('SSDS', 'SSAS', 'SSRS')] [string[]]$Component = @('SSDS', 'SSAS', 'SSRS'), - [pscredential]$Credential, - [bool]$EnableException = $EnableException + [pscredential]$Credential ) begin { @@ -297,11 +296,8 @@ function Get-SQLInstanceComponent { } process { foreach ($computer in $ComputerName) { - try { - $results = Invoke-Command2 -ComputerName $computer -ScriptBlock $regScript -Credential $Credential -ErrorAction Stop -Raw -ArgumentList @($Component) -RequiredPSVersion 3.0 - } catch { - Stop-Function -Message "Failed to get instance components from $computer" -ErrorRecord $_ -Continue - } + $results = Invoke-Command2 -ComputerName $computer -ScriptBlock $regScript -Credential $Credential -ErrorAction Stop -Raw -ArgumentList @($Component) -RequiredPSVersion 3.0 + # Log is stored in the log property, pile it all into the debug log foreach ($logEntry in $results.Log) { Write-Message -Level Debug -Message $logEntry @@ -314,7 +310,7 @@ function Get-SQLInstanceComponent { $newVersion = New-Object -TypeName System.Version -ArgumentList ($newVersion.Major , ($newVersion.Minor - $newVersion.Minor % 10), $newVersion.Build) Write-Message -Level Debug -Message "Converted version $($result.Version) to $newVersion" #Find a proper build reference and replace Version property - $result.Version = Get-DbaBuildReference -Build $newVersion + $result.Version = Get-DbaBuildReference -Build $newVersion -EnableException $result | Select-Object -ExcludeProperty Log } } diff --git a/internal/functions/Test-PendingReboot.ps1 b/internal/functions/Test-PendingReboot.ps1 index 55fba0c49e..be3affc1f7 100644 --- a/internal/functions/Test-PendingReboot.ps1 +++ b/internal/functions/Test-PendingReboot.ps1 @@ -17,47 +17,42 @@ function Test-PendingReboot { [Parameter(Mandatory)] [ValidateNotNullOrEmpty()] [DbaInstanceParameter]$ComputerName, - [ValidateNotNullOrEmpty()] - [pscredential]$Credential, - [bool]$EnableException = $EnableException + [pscredential]$Credential ) process { - try { - $icmParams = @{ - ComputerName = $ComputerName.ComputerName - Raw = $true - } - if ($PSBoundParameters.ContainsKey('Credential')) { - $icmParams.Credential = $Credential - } - - $OperatingSystem = Get-DbaCmObject -ComputerName $ComputerName.ComputerName -ClassName Win32_OperatingSystem + $icmParams = @{ + ComputerName = $ComputerName.ComputerName + Raw = $true + ErrorAction = 'Stop' + } + if (Test-Bound -ParameterName Credential) { + $icmParams.Credential = $Credential + } - # If Vista/2008 & Above query the CBS Reg Key - If ($OperatingSystem.BuildNumber -ge 6001) { - $PendingReboot = Invoke-Command2 @icmParams -ScriptBlock { Get-ItemProperty -Path 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Component Based Servicing' -Name 'RebootPending' -ErrorAction SilentlyContinue } - if ($PendingReboot) { - Write-Message -Level Verbose -Message 'Reboot pending detected in the Component Based Servicing registry key' - return $true - } - } + $OperatingSystem = Get-DbaCmObject -ComputerName $ComputerName.ComputerName -ClassName Win32_OperatingSystem -EnableException - # Query WUAU from the registry - $PendingReboot = Invoke-Command2 @icmParams -ScriptBlock { Get-ItemProperty -Path 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\WindowsUpdate\Auto Update' -Name 'RebootRequired' -ErrorAction SilentlyContinue } + # If Vista/2008 & Above query the CBS Reg Key + If ($OperatingSystem.BuildNumber -ge 6001) { + $PendingReboot = Invoke-Command2 @icmParams -ScriptBlock { Get-ItemProperty -Path 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Component Based Servicing' -Name 'RebootPending' -ErrorAction SilentlyContinue } if ($PendingReboot) { - Write-Message -Level Verbose -Message 'WUAU has a reboot pending' + Write-Message -Level Verbose -Message 'Reboot pending detected in the Component Based Servicing registry key' return $true } + } - # Query PendingFileRenameOperations from the registry - $PendingReboot = Invoke-Command2 @icmParams -ScriptBlock { Get-ItemProperty -Path 'HKLM:\SYSTEM\CurrentControlSet\Control\Session Manager' -Name 'PendingFileRenameOperations' -ErrorAction SilentlyContinue } - if ($PendingReboot -and $PendingReboot.PendingFileRenameOperations) { - Write-Message -Level Verbose -Message 'Reboot pending in the PendingFileRenameOperations registry value' - return $true - } - return $false - } catch { - Stop-Function -Message "Failed to obtain any intormation from remote registry on $ComputerName" -ErrorRecord $_ + # Query WUAU from the registry + $PendingReboot = Invoke-Command2 @icmParams -ScriptBlock { Get-ItemProperty -Path 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\WindowsUpdate\Auto Update' -Name 'RebootRequired' -ErrorAction SilentlyContinue } + if ($PendingReboot) { + Write-Message -Level Verbose -Message 'WUAU has a reboot pending' + return $true + } + + # Query PendingFileRenameOperations from the registry + $PendingReboot = Invoke-Command2 @icmParams -ScriptBlock { Get-ItemProperty -Path 'HKLM:\SYSTEM\CurrentControlSet\Control\Session Manager' -Name 'PendingFileRenameOperations' -ErrorAction SilentlyContinue } + if ($PendingReboot -and $PendingReboot.PendingFileRenameOperations) { + Write-Message -Level Verbose -Message 'Reboot pending in the PendingFileRenameOperations registry value' + return $true } + return $false } } \ No newline at end of file