Skip to content
Merged
Show file tree
Hide file tree
Changes from 14 commits
Commits
Show all changes
15 commits
Select commit Hold shift + click to select a range
4270d24
New-DbaAvailabilityGroup - Check the last progress record of each Id …
andreasjordan Oct 11, 2026
e2b5e3d
Sync-DbaAvailabilityGroup - Close the dedicated admin connection also…
andreasjordan Oct 17, 2026
0b8ffb9
Invoke-DbaDbDataGenerator - Close the connection for the inserts also…
andreasjordan Oct 17, 2026
52c952f
Invoke-DbaDbDataMasking - Clean up in finally blocks and stop writing…
andreasjordan Oct 17, 2026
f1c3ff9
Invoke-DbaAdvancedRestore - Stop the database after a failed restore …
andreasjordan Oct 17, 2026
75d3ee4
Invoke-DbaAdvancedInstall - Return a result when the configuration fi…
andreasjordan Oct 17, 2026
1460bca
Invoke-DbaDbLogShipRecovery - Stop writing a $null before the result …
andreasjordan Oct 17, 2026
f242ecf
Install-DbaInstance - Use the name given when the computer name canno…
andreasjordan Oct 17, 2026
e763c3a
New-DbaComputerCertificate - Remove the request folder in the finally…
andreasjordan Oct 17, 2026
80f3b17
Install-DbaSqlPackage - Download nothing with -WhatIf
andreasjordan Oct 17, 2026
9e99e49
Save-DbaKbUpdate - Report a failed download with Stop-Function
andreasjordan Oct 17, 2026
2b00530
Invoke-DbaDbLogShipRecovery - Create the folder of the database below…
andreasjordan Oct 17, 2026
136a2fc
New-DbaComputerCertificate - Test the removal of the request folder a…
andreasjordan Oct 17, 2026
f128350
New-DbaComputerCertificate - Guess the full name of a computer from i…
andreasjordan Oct 17, 2026
fffabc7
Invoke-DbaAdvancedRestore - Never restore with -VerifyOnly
andreasjordan Oct 19, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 11 additions & 2 deletions public/Install-DbaInstance.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -566,8 +566,17 @@ function Install-DbaInstance {
}
# resolve names
Write-ProgressHelper -TotalSteps $totalSteps -Activity $activity -StepNumber ($stepCounter++) -Message "Resolving computer name"
$resolvedName = Resolve-DbaNetworkName -ComputerName $computer -Credential $Credential
if ($computer.IsLocalHost) {
# Without a resolved name, the name given is used, as Update-DbaInstance does. An empty name made every
# later step fail on it, starting with the check for a pending reboot.
try {
$resolvedName = Resolve-DbaNetworkName -ComputerName $computer -Credential $Credential -EnableException
} catch {
Write-Message -Level Verbose -Message "Could not resolve $($computer.ComputerName) (this may occur with CredSSP or workgroup environments). Using provided name directly."
$resolvedName = $null
}
if (-not $resolvedName) {
$fullComputerName = $computer.ComputerName
} elseif ($computer.IsLocalHost) {
# Don't add a domain to localhost as this might add a domain that is later not recognized by .IsLocalHost anymore (#6976).
$fullComputerName = $resolvedName.ComputerName
} else {
Expand Down
9 changes: 8 additions & 1 deletion public/Install-DbaSqlPackage.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -212,7 +212,8 @@ function Install-DbaSqlPackage {
}

# Download if needed
if (-not (Test-Path -Path $LocalFile) -or $Force) {
# The download is real work, so -WhatIf has to skip it too, and not only the installation.
if ((-not (Test-Path -Path $LocalFile) -or $Force) -and $Pscmdlet.ShouldProcess($url, "Download SqlPackage to $LocalFile")) {
try {
Write-Progress -Activity "Installing SqlPackage" -Status "Starting download from Microsoft..." -PercentComplete 20
Write-Message -Level Verbose -Message "Downloading SqlPackage from $url"
Expand Down Expand Up @@ -290,6 +291,12 @@ function Install-DbaSqlPackage {
}
}

# With -WhatIf nothing was downloaded or installed, so there is nothing to verify. The verification warned that
# the installation failed when SqlPackage was not there yet.
if ($WhatIfPreference) {
return
}

Write-Progress -Activity "Installing SqlPackage" -Status "Verifying installation..." -PercentComplete 90

# Verify installation
Expand Down
15 changes: 12 additions & 3 deletions public/Invoke-DbaAdvancedInstall.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -232,7 +232,7 @@ function Invoke-DbaAdvancedInstall {
$restartNeeded = Test-PendingReboot -ComputerName $ComputerName -Credential $Credential -NoPendingRename:$NoPendingRenameCheck
} catch {
$restartNeeded = $false
Stop-Function -Message "Failed to get reboot status from $computer" -ErrorRecord $_
Stop-Function -Message "Failed to get reboot status from $ComputerName" -ErrorRecord $_
}
if ($restartNeeded -and $Restart) {
# Restart the computer prior to doing anything
Expand Down Expand Up @@ -282,8 +282,17 @@ function Invoke-DbaAdvancedInstall {
$null = Send-File -Path $ConfigurationPath -Destination $chosenPath -Session $session -ErrorAction Stop
$session | Remove-PSSession
} catch {
Stop-Function -Message "Failed to copy file $($ConfigurationPath) to $remoteConfig on $($ComputerName), exiting" -ErrorRecord $_
return
# Like the other failures below, this one returns its result object, so the caller gets a result for the
# computer. The session and the local configuration file are cleaned up here, because the cleanup in the
# finally of the installation is not reached from here.
$msg = "Failed to copy file $($ConfigurationPath) to $remoteConfig on $($ComputerName), exiting"
Stop-Function -Message $msg -ErrorRecord $_
$output.Notes += $msg
if ($session) {
$session | Remove-PSSession
}
Remove-Item -Path $ConfigurationPath -ErrorAction SilentlyContinue
return $output
}
}
$installParams = $ArgumentList
Expand Down
9 changes: 6 additions & 3 deletions public/Invoke-DbaAdvancedRestore.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -542,14 +542,15 @@ function Invoke-DbaAdvancedRestore {
Write-Progress -id 1 -activity "Verifying $database backup file on $SqlInstance - Backup $BackupCnt of $($Backups.count)" -percentcomplete 0 -status ([System.String]::Format("Progress: {0} %", 0))
$verify = $restore.SqlVerify($server)
Write-Progress -id 1 -activity "Verifying $database backup file on $SqlInstance - Backup $BackupCnt of $($Backups.count)" -status "Complete" -Completed
# No return here: it left the whole end block, so only the first backup file was verified.
if ($verify) {
Write-Message -Message "VerifyOnly restore Succeeded" -Level Verbose
$restoreComplete = $true
return "Verify successful"
"Verify successful"

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[P1] Keep all newly reached backups in VerifyOnly mode

Removing the return lets verification reach the last backup, but the dispatch above checks ($KeepCDC -or $ErrorBrokerConversations) -and -not $restore.NoRecovery before VerifyOnly. For two full backups of the same database, the first has NoRecovery=true and is verified; the last has NoRecovery=false and enters the earlier branch, which calls ConnectionContext.ExecuteNonQuery with real RESTORE SQL.

A concrete path is Restore-DbaDatabase over a directory containing multiple full backups with -VerifyOnly -KeepCDC (or Invoke-DbaAdvancedRestore with those backup records). Restore-DbaDatabase retains all records in verification mode and forwards these options. If the existing restore splat also includes -WithReplace, an idle existing target can be overwritten rather than merely verified.

I independently executed the exact base/head dispatch branches using a recording boundary: base recorded only VERIFY first-full.bak; head recorded that followed by EXECUTE RESTORE DATABASE [Probe] FROM DISK='last-full.bak' WITH RECOVERY, REPLACE, KEEP_CDC.

Make VerifyOnly take precedence over every branch that can execute restore SQL while retaining verification of all files. Add a multi-backup regression with KeepCDC or ErrorBrokerConversations that checks every file is verified and no target database is created, restored, or recovered.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Confirmed, thanks. Fixed in fffabc7: the branch for -KeepCDC/-ErrorBrokerConversations and the page restore branch now require -not $VerifyOnly, so a verification never executes a restore statement. It was reachable before this PR as well: a single full backup is the last file and recovers, so -VerifyOnly -KeepCDC took that branch for it.

The new context "When -VerifyOnly with -KeepCDC verifies two full backups" builds the history the way Restore-DbaDatabase hands it over for -VerifyOnly, without the selection, with a new database name and new file names, and checks that both files are verified and that no database exists afterwards.

Lab, Windows PowerShell 5.1, InstanceSingle SQL Server 2019: Invoke-DbaAdvancedRestore.Tests.ps1 passes 21 of 21, and Restore-DbaDatabase.Tests.ps1, its caller, passes 86 with 3 skipped (the Azure contexts), as before. With the Invoke-DbaAdvancedRestore.ps1 of f128350, the new context fails exactly as you describe: one "Verify successful" instead of two, and the restore of the second full backup created the database.


This text was created by Claude and reviewed by Andreas Jordan.

} else {
Write-Message -Message "VerifyOnly restore Failed" -Level Warning
$restoreComplete = $False
return "Verify failed"
"Verify failed"
}
} else {
$outerProgress = $BackupCnt / $Backups.Count * 100
Expand Down Expand Up @@ -616,7 +617,9 @@ function Invoke-DbaAdvancedRestore {
Write-Message -Level Verbose -Message "Failed to restore $database"
$restoreComplete = $False
$ExitError = $_.Exception.InnerException
Stop-Function -Message "Failed to restore db $database, stopping" -ErrorRecord $_ -Continue
# No -Continue: it continued with the next backup file of this database, so the break that
# stops the database and goes on with the next one was never reached.
Stop-Function -Message "Failed to restore db $database, stopping" -ErrorRecord $_
break
} finally {
# The bar of this backup file ends with the file, also when its restore failed or was stopped.
Expand Down
14 changes: 8 additions & 6 deletions public/Invoke-DbaDbDataGenerator.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -595,12 +595,14 @@ function Invoke-DbaDbDataGenerator {
}
} finally {
Write-ProgressHelper -Completed
}

try {
$sqlconn.Close()
} catch {
Stop-Function -Message "Failure" -Continue -ErrorRecord $_
# The returns above, a throw under EnableException and a stopped pipeline skip everything after this
# block, so the connection is closed here. A warning instead of Stop-Function, because a throw from a
# finally would replace the error that is on its way out.
try {
$sqlconn.Close()
} catch {
Write-Message -Level Warning -Message "Failure closing the connection to $instance" -ErrorRecord $_
}
}
}
}
Expand Down
Loading
Loading