Restore-SQL-Database.ps1
<#PSScriptInfo .VERSION 1.1 .GUID 5749b455-e6a7-44fe-a012-d0e80c97a437 .AUTHOR Andreas Kahlroth .COMPANYNAME .COPYRIGHT .TAGS .LICENSEURI .PROJECTURI .ICONURI .EXTERNALMODULEDEPENDENCIES .REQUIREDSCRIPTS .EXTERNALSCRIPTDEPENDENCIES .RELEASENOTES #> <# .DESCRIPTION Restore SQL database #> param() function Restore-SQL-Database { param( [Parameter(Mandatory=$true)] [string]$SqlBackupFile, [string]$SqlServer="localhost", [Parameter(Mandatory=$true)] [string]$SqlDatabase, [string]$SqlServerLogin=$SqlDatabase, [string]$SqlServerLoginPassword="Passw0rd", [string]$SqlDatabaseUser=$SqlDatabase ) Write-Host "[INFO] Start Restore-SQL-Database" $currentLocation = Get-Location #Check if backupfile exists if(!(Test-Path -Path $SqlBackupFile)) { Write-Error "Path to $SqlBackupFile is invalid" exit } Write-Host "[INFO] Server: $SqlServer" Write-Host "[INFO] Database: $SqlDatabase" Write-Host "[INFO] Server Login: $SqlServerLogin" Write-Host "[INFO] Database User: $SqlDatabaseUser" Write-Host "[INFO] Backup: $SqlBackupFile" #Load SMO assemblies [System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SqlServer.SMO") | Out-Null [System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SqlServer.SmoExtended") | Out-Null #Set restore configurations $server = New-Object -Type Microsoft.SqlServer.Management.Smo.Server -Argumentlist $SqlServer $server.ConnectionContext.StatementTimeout = 0 $smoRestore = New-Object -Type Microsoft.SqlServer.Management.Smo.Restore $backupDevice = New-Object -Type Microsoft.SqlServer.Management.Smo.BackupDeviceItem -Argumentlist $SqlBackupFile,"File" $smoRestore.Devices.Add($backupDevice) $smoRestore.NoRecovery = $false $smoRestore.ReplaceDatabase = $true $smoRestore.Action = "Database" $smoRestore.PercentCompleteNotification = 10 $percentEventHandler = [Microsoft.SqlServer.Management.Smo.PercentCompleteEventHandler] { Write-Host "[INFO] Restoring $($_.Percent)%" } $completedEventHandler = [Microsoft.SqlServer.Management.Common.ServerMessageEventHandler] { Write-Host "[INFO] Restore of database $SqlDatabase with $SqlBackupFile completed" } $smoRestore.add_PercentComplete($percentEventHandler) $smoRestore.add_Complete($completedEventHandler) $smoRestoreDetails = $smoRestore.ReadBackupHeader($server) #Get data/logfile names from backupfile $DBLogicalNameDT= $smoRestore.ReadFileList($server) foreach ($row in $DBLogicalNameDT) { $FileType = $row["Type"].ToUpper() if ($FileType.Equals("D")) { $dBLogicalName = $row["LogicalName"] } elseif ($FileType.Equals("L")) { $logLogicalName = $row["LogicalName"] } } #Data- and logfile paths $dbDataFile = "$($server.Settings.DefaultFile)$($SqlDatabase).mdf" $dbLogFile = "$($server.Settings.DefaultLog)$($SqlDatabase)_log.ldf" Write-Host "[INFO] Data: $dbDataFile" Write-Host "[INFO] Log: $dbLogFile" #Set restore configurations $smoRestore.Database = $SqlDatabase $dbRestoreFile = New-Object -Type Microsoft.SqlServer.Management.Smo.RelocateFile $dbRestoreLog = New-Object -Type Microsoft.SqlServer.Management.Smo.RelocateFile $dbRestoreFile.LogicalFileName = $dBLogicalName $dbRestoreFile.PhysicalFileName = $dbDataFile $dbRestoreLog.LogicalFileName = $logLogicalName $dbRestoreLog.PhysicalFileName = $dbLogFile $smoRestore.RelocateFiles.Add($dbRestoreFile) | Out-Null $smoRestore.RelocateFiles.Add($dbRestoreLog) | Out-Null #Create databas if it dont exists if(!($server.Databases[$SqlDatabase])) { $db = New-Object -Type Microsoft.SqlServer.Management.Smo.Database -Argumentlist $server,$SqlDatabase $db.Create() Write-Host "[INFO] Created database $($db.Name)" } #Drop SQL connections $killConnectionsSQL = "DECLARE @dbname sysname " + ` "SET @dbname = '$SqlDatabase' " + ` "DECLARE @spid int " + ` "SELECT @spid = min(spid) FROM master.dbo.sysprocesses " + ` "WHERE dbid = db_id(@dbname) " + ` "WHILE @spid Is Not Null " + ` "BEGIN " + ` "EXEC ('Kill ' + @spid) " + ` "SELECT @spid = min(spid) FROM master.dbo.sysprocesses " + ` "WHERE dbid = db_id(@dbname) and spid > @spid " + ` "END" $masterDb = $server.Databases["master"] $masterDb.ExecuteNonQuery($killConnectionsSQL) Write-Host "[INFO] Dropped connections to $SqlDatabase" #Restore backup to db Write-Host "[INFO] Starting restore of $SqlDatabase" $smoRestore.SqlRestore($server) $db = $server.Databases[$SqlDatabase] #Re-create service broker $serviceBrokerSql = "ALTER DATABASE [$SqlDatabase] SET NEW_BROKER with rollback immediate" $db.ExecuteNonQuery($serviceBrokerSql) Write-Host "[INFO] Re-created service broker" #Rename log and datafile logical names if($($db.FileGroups[0].Files[0].Name) -cne $SqlDatabase) { $db.FileGroups[0].Files[0].Rename($SqlDatabase) Write-Host "[INFO] Renamed datafile logical name to $SqlDatabase" } if($($db.LogFiles[0].Name) -cne "$($SqlDatabase)_log") { $db.LogFiles[0].Rename("$($SqlDatabase)_log") Write-Host "[INFO] Renamed logfile logical name to $($SqlDatabase)_log" } #Shrink logfile (.ldf) to 0KB $db.RecoveryModel = [Microsoft.SqlServer.Management.Smo.RecoveryModel]::Simple $db.Alter() $db.LogFiles[0].Shrink(0,[Microsoft.SqlServer.Management.Smo.ShrinkMethod]::TruncateOnly) $db.LogFiles.Refresh($true) $db.RecoveryModel = [Microsoft.SqlServer.Management.Smo.RecoveryModel]::Full $db.Alter() Write-Host "[INFO] Logfile shrunk to $($db.LogFiles[0].Size/1KB) KB" #Create login if it dont exists if(!($server.Logins[$SqlServerLogin])) { $login = New-Object -Type Microsoft.SqlServer.Management.Smo.Login -Argumentlist $server,$SqlDatabase $login.LoginType = [Microsoft.SqlServer.Management.Smo.LoginType]::SqlLogin $login.PasswordExpirationEnabled = $false $login.PasswordPolicyEnforced = $false $login.DefaultDatabase = $SqlDatabase $login.Create($SqlServerLoginPassword) Write-Host "[INFO] Created SQLServer login $($login.Name)" } #Re-create database user if ($db.Users[$SqlDatabaseUser]) { #Remove brokerservices owned by user [System.Collections.ArrayList]$brokerServices = $db.ServiceBroker.Services foreach($service in $brokerServices) { if($service.Owner -like $SqlDatabaseUser) { $service.Drop() Write-Host "[INFO] Dropped $($service.Name)" } } #Drop user $db.Users[$SqlDatabaseUser].Drop() } $databaseUser = New-Object -TypeName Microsoft.SqlServer.Management.Smo.User -ArgumentList $db,$SqlDatabaseUser $databaseUser.Login = $SqlServerLogin $databaseUser.DefaultSchema = "backend" $databaseUser.Create() #Assign database role for new user $databaserole = $db.Roles["db_owner"] $databaserole.AddMember($SqlDatabaseUser) $databaserole.Alter | Out-Null Write-Host "[INFO] Re-created database user $SqlDatabaseUser" Set-Location -Path $currentLocation Write-Host "[DONE]" -ForegroundColor White -BackgroundColor Green Write-Host "" } |