Use SQL PS module

This commit is contained in:
2025-10-22 13:19:32 +01:00
parent e576ee3954
commit 5a26b80bb6

View File

@@ -9,11 +9,36 @@ param(
[switch]$Force [switch]$Force
) )
#
# backup.ps1 # backup.ps1
# #
# TODO: Parallelize backups for multiple DBs in the instance # TODO: Parallelize backups for multiple DBs in the instance
# TODO: Use PowerShell SQL module instead of sqlcmd
# Import SQL Server PowerShell module
try {
# Try to import the newer SqlServer module first
if (Get-Module -ListAvailable -Name SqlServer) {
Import-Module SqlServer -ErrorAction Stop
Write-Host "INFO: SqlServer PowerShell module loaded successfully."
}
# Fall back to older SQLPS module if available
elseif (Get-Module -ListAvailable -Name SQLPS) {
Import-Module SQLPS -ErrorAction Stop
Write-Host "INFO: SQLPS PowerShell module loaded successfully."
}
else {
throw "No SQL Server PowerShell module found"
}
# Verify Invoke-Sqlcmd is available
if (-not (Get-Command Invoke-Sqlcmd -ErrorAction SilentlyContinue)) {
throw "Invoke-Sqlcmd command not available"
}
}
catch {
Write-Host "ERROR: Failed to import SQL Server PowerShell module. Please install it using: Install-Module -Name SqlServer -AllowClobber"
Write-Host "ERROR: $($_.Exception.Message)"
exit 1
}
$instanceName = $SqlInstance.Split('\')[1] $instanceName = $SqlInstance.Split('\')[1]
@@ -158,16 +183,89 @@ if ((Get-Date).DayOfWeek -eq $fullBackupDay) {
$query = "EXECUTE [dbo].[DatabaseBackup] @Databases = 'ALL_DATABASES', @Directory = '$directory', @BackupType = '$backupType', @Verify = 'N', @CleanupTime = $cleanupTime, @CheckSum = 'Y', @LogToTable = 'Y'" $query = "EXECUTE [dbo].[DatabaseBackup] @Databases = 'ALL_DATABASES', @Directory = '$directory', @BackupType = '$backupType', @Verify = 'N', @CleanupTime = $cleanupTime, @CheckSum = 'Y', @LogToTable = 'Y'"
Write-Log "Executing backup type: $backupType" Write-Log "Executing backup type: $backupType"
Write-Log "SQL Query: $query"
$sqlcmdOutput = & sqlcmd -S $SqlInstance -Q $query 2>&1 try {
$sqlcmdExitCode = $LASTEXITCODE # Execute the backup using PowerShell SQL module with better error handling
# Capture verbose output from Ola H scripts
$infoMessages = @()
if ($sqlcmdExitCode -eq 0) { # Create event handlers to capture SQL Server messages
foreach ($line in $sqlcmdOutput) { $connection = New-Object System.Data.SqlClient.SqlConnection
Write-Log $line $connection.ConnectionString = "Server=$SqlInstance;Integrated Security=true;Connection Timeout=30"
# Event handler for informational messages (PRINT statements)
$connection.add_InfoMessage({
param($sqlSender, $e)
$message = $e.Message
if ($message -and $message.Trim() -ne "") {
$script:infoMessages += $message
Write-Log "SQL INFO: $message"
}
})
try {
$connection.Open()
$command = New-Object System.Data.SqlClient.SqlCommand
$command.Connection = $connection
$command.CommandText = $query
$command.CommandTimeout = 0 # No timeout for backup operations
Write-Log "Executing SQL command with message capture..."
# Execute and capture any result sets
$reader = $command.ExecuteReader()
# Process any result sets
while ($reader.Read()) {
$rowData = @()
for ($i = 0; $i -lt $reader.FieldCount; $i++) {
$rowData += "$($reader.GetName($i)): $($reader.GetValue($i))"
}
if ($rowData.Count -gt 0) {
Write-Log "SQL RESULT: $($rowData -join ', ')"
}
}
$reader.Close()
} }
Write-Log "$backupType Backup execution completed." finally {
} else { if ($connection.State -eq [System.Data.ConnectionState]::Open) {
Write-Log "ERROR: Backup execution failed. Exit code: $sqlcmdExitCode. Output: $sqlcmdOutput" $connection.Close()
}
$connection.Dispose()
}
Write-Log "$backupType Backup execution completed successfully."
Write-Log "Total informational messages captured: $($infoMessages.Count)"
}
catch {
Write-Log "ERROR: Backup execution failed with exception: $($_.Exception.Message)"
# Log additional SQL Server error details if available
if ($_.Exception.InnerException) {
Write-Log "ERROR: Inner Exception: $($_.Exception.InnerException.Message)"
}
# Check for SQL Server specific errors
if ($_.Exception -is [System.Data.SqlClient.SqlException]) {
Write-Log "ERROR: SQL Server Error Details:"
foreach ($sqlError in $_.Exception.Errors) {
Write-Log "ERROR: Severity: $($sqlError.Class), State: $($sqlError.State), Number: $($sqlError.Number)"
Write-Log "ERROR: Message: $($sqlError.Message)"
if ($sqlError.Procedure) {
Write-Log "ERROR: Procedure: $($sqlError.Procedure), Line: $($sqlError.LineNumber)"
}
}
}
# Clean up connection if it exists
if ($connection -and $connection.State -eq [System.Data.ConnectionState]::Open) {
$connection.Close()
$connection.Dispose()
}
exit 1
} }