Using PowerShell to manage multiple FIM scenarios on a lab computer
When testing various lab scenarios with FIM, it is a good idea to avoid side effects by just having the data deployed that is relevant for a given scenario.The probably simplest method to have multiple scenarios deployed on a single FIM server is to operate with database backups.To simplify the scenario based database management in a lab environment, I wrote a collection of scripts. The idea of the implementation outlined in this post is to create a folder per scenario:
To keep the logic of the script files simple, each scenario folder has a copy of all script files:
While I like PowerShell, I do also like convenience.Part of this is the ability to start a PowerShell script by double-clicking it.One way of accomplishing this is to use a VBScript to run a PowerShell script.The related VBScript has only 5 lines of script code:
Option Explicit
Dim oShell, appCmd
Set oShell = CreateObject("WScript.Shell")
appCmd = "powershell -noexit &'" & Replace(WScript.ScriptFullName, ".vbs", ".ps1") & "'"
oShell.Run appCmd, 4, false
To avoid the need for modifying the script code for each PowerShell script you want to run this way, you just need to save the VBScript in the folder where your PowerShell script is stored.In addition to this, the VBScript must have the same name as the related PowerShell script.The gist of the VBScript code is very simple:
The script code
Reads its full name
Replaces the extension .vbs with .ps1
Starts PowerShell with the calculated PowerShell script name as parameter.
Backing up the FIM databases
In my testing, I found it helpful to stop the FIM Service and the FIM Synchronization Service and also to restart the SQL Service prior to taking the database backups.That way, you can make sure that there are no open database handles.After taking care of these services, the script codes takes the database backups and stores the related files in the current folder.There is no need to specify parameters for this operation.
#--------------------------------------------------------------------------------------------------------------------------
set-variable -name FimServiceDb -value "FIMService" -option constant
set-variable -name FimSyncDb -value "FIMSynchronizationService" -option constant
set-variable -name ConString -value "Provider=SQLOLEDB;Data Source=localhost;Trusted_Connection=Yes;Initial Catalog=master;"
$curFolder = Split-Path -Parent $MyInvocation.MyCommand.Path
#------------------------------------------------------------------------------------------------------------------------------------
write-host "Processing database backup"
write-host "=========================="
write-host "Step 1 of 7: Stopping FIM Service"
$fimService = get-service "FIMService"
if($fimService.status -ne "Stopped") {stop-Service "FIMService"}
#------------------------------------------------------------------------------------------------------------------------------------
write-host "Step 2 of 7: Stopping FIM Synchronization Service"
$syncService = get-service "FIMSynchronizationService"
if($syncService.status -ne "Stopped") {stop-Service "FIMSynchronizationService"}
#------------------------------------------------------------------------------------------------------------------------------------
write-host "Step 3 of 7: Restarting SQL Server Service"
$sqlService = get-service "MSSQLSERVER"
restart-Service "MSSQLSERVER" -force
write-host "WARNING: Waiting for service '"$sqlService.name"' to finish starting..." -foregroundcolor yellow -backgroundcolor black
start-sleep -s 10
if($sqlService.status -ne "Running") {throw "SQL Service is not running"}
#------------------------------------------------------------------------------------------------------------------------------------
write-host "Step 4 of 7: Backing up FIM Service database"
$connection = New-Object System.Data.OleDb.OleDbConnection $ConString
$connection.Open()
$fileName = $curFolder + "\" + $FimServiceDb + ".bak"
$sqlCmd = "BACKUP DATABASE " + $FimServiceDb + " TO DISK = '" + $fileName + "' WITH FORMAT"
$cmd1 = New-Object System.Data.OleDb.OleDbCommand $sqlCmd,$connection
$cmd1.executenonquery()|out-null
#------------------------------------------------------------------------------------------------------------------------------------
write-host "Step 5 of 7: Backing up FIM Synchronization Service database"
$fileName = $curFolder + "\" + $FimSyncDb + ".bak"
$sqlCmd = "BACKUP DATABASE " + $FimSyncDb + " TO DISK = '" + $fileName + "' WITH FORMAT"
$cmd1 = New-Object System.Data.OleDb.OleDbCommand $sqlCmd,$connection
$cmd1.executenonquery()|out-null
$connection.Close()
#------------------------------------------------------------------------------------------------------------------------------------
write-host "Step 6 of 7: Starting FIM Service"
$fimService = get-service "FIMService"
if($fimService.status -eq "Stopped") {start-Service "FIMService"}
#------------------------------------------------------------------------------------------------------------------------------------
write-host "Step 7 of 7: Starting FIM Synchronization Service"
$syncService = get-service "FIMSynchronizationService"
if($syncService.status -eq "Stopped") {start-Service "FIMSynchronizationService"}
#--------------------------------------------------------------------------------------------------------------------------
write-host "`nCommand completed successfully`n"
#--------------------------------------------------------------------------------------------------------------------------
trap
{
Write-Host "`nError: $($_.Exception.Message)`n" -foregroundcolor white -backgroundcolor darkred
Exit
}
#--------------------------------------------------------------------------------------------------------------------------
Restoring the FIM databases
The database restore works pretty much the same way as the database backup.First, the FIM Service and the FIM Synchronization Service are stopped and the SQL Server service is restarted.Then, the script code uses the backup files in the current folder to restore to a database state.
#------------------------------------------------------------------------------------------------------------------------------------
set-variable -name FimServiceDb -value "FIMService" -option constant
set-variable -name FimSyncDb -value "FIMSynchronizationService" -option constant
set-variable -name ConString -value "Provider=SQLOLEDB;Data Source=localhost;Trusted_Connection=Yes;Initial Catalog=master;"
#------------------------------------------------------------------------------------------------------------------------------------
$curFolder = Split-Path -Parent $MyInvocation.MyCommand.Path
$fimServicedBPath = $curFolder + "\" + $FimServiceDb + ".bak"
$fimSyncServicedBPath = $curFolder + "\" + $FimSyncDb + ".bak"
if((test-path $fimServicedBPath) -eq $false)
{throw "FIM service database backup not found"}
if((test-path $fimSyncServicedBPath) -eq $false)
{throw "FIM synchronization service database backup not found"}
#------------------------------------------------------------------------------------------------------------------------------------
write-host "Processing FIM Database Restore"
write-host "==============================="
write-host "Step 1 of 7: Stopping FIM Service"
$fimService = get-service "FIMService"
if($fimService.status -ne "Stopped") {stop-Service "FIMService"}
#------------------------------------------------------------------------------------------------------------------------------------
write-host "Step 2 of 7: Stopping FIM Synchronization Service"
$syncService = get-service "FIMSynchronizationService"
if($syncService.status -ne "Stopped") {stop-Service "FIMSynchronizationService"}
#------------------------------------------------------------------------------------------------------------------------------------
write-host "Step 3 of 7: Restarting SQL Server Service"
$sqlService = get-service "MSSQLSERVER"
restart-Service "MSSQLSERVER" -force
write-host "WARNING: Waiting for service '"$sqlService.name"' to finish starting..." -foregroundcolor yellow -backgroundcolor black
start-sleep -s 10
if($sqlService.status -ne "Running") {throw "SQL Service is not running"}
#------------------------------------------------------------------------------------------------------------------------------------
write-host "Step 4 of 7: Restoring FIM Service database"
$connection = New-Object System.Data.OleDb.OleDbConnection $ConString
$connection.Open()
$fileName = $curFolder + "\" + $FimServiceDb + ".bak"
$sqlCmd = "RESTORE DATABASE " + $FimServiceDb + " FROM DISK = '" + $fileName + "' WITH REPLACE"
$cmd1 = New-Object System.Data.OleDb.OleDbCommand $sqlCmd,$connection
$cmd1.executenonquery()|out-null
#------------------------------------------------------------------------------------------------------------------------------------
write-host "Step 5 of 7: Restoring FIM Synchronization Service database"
$fileName = $curFolder + "\" + $FimSyncDb + ".bak"
$sqlCmd = "RESTORE DATABASE " + $FimSyncDb + " FROM DISK = '" + $fileName + "' WITH REPLACE"
$cmd1 = New-Object System.Data.OleDb.OleDbCommand $sqlCmd,$connection
$cmd1.executenonquery()|out-null
$connection.Close()
#------------------------------------------------------------------------------------------------------------------------------------
write-host "Step 6 of 7: Starting FIM Service"
$fimService = get-service "FIMService"
if($fimService.status -eq "Stopped") {start-Service "FIMService"}
#------------------------------------------------------------------------------------------------------------------------------------
write-host "Step 7 of 7: Starting FIM Synchronization Service"
$syncService = get-service "FIMSynchronizationService"
if($syncService.status -eq "Stopped") {start-Service "FIMSynchronizationService"}
#------------------------------------------------------------------------------------------------------------------------------------
write-host "`nCommand completed successfully`n"
#------------------------------------------------------------------------------------------------------------------------------------
trap
{
Write-Host "`nError: $($_.Exception.Message)`n" -foregroundcolor white -backgroundcolor darkred
Exit
}
#------------------------------------------------------------------------------------------------------------------------------------
Conclusion
As indicated in the introduction, the scripts in this post are not meant to replace a professional backup solution for a production environment.The idea is to provide a quick and convenient way to manage various scenarios on a lab machine.If you have feedback or even suggestions for improvements, please reply to this post.
Markus Vilcinskas, Knowledge Engineer, Microsoft Corporation
October 26th, 2009 11:11pm
Hi Markus, thanks for these scripts, they are very useful indeed! Just a small note: before restarting the services at the end, you are checking the service status against the old result of the get-service call, therefore the services are not restarted. You should repeat the call to get-service to get the updated status of the services. Cheers, PaoloPaolo Tedesco - http://cern.ch/idm
Free Windows Admin Tool Kit Click here and download it now
December 17th, 2009 3:01pm
Thanks a lot, Paolo, good catch!Fixed...Cheers,MarkusMarkus Vilcinskas, Knowledge Engineer, Microsoft Corporation
December 17th, 2009 5:11pm
Great scripts, thanks Markus!
I was experiencing command timeouts when I ran them though, so I increased the timeout value by adding the following lines:
After this line (occurs twice)
$cmd1 = New-Object System.Data.OleDb.OleDbCommand $sqlCmd,$connection
Add this line (after each)
$cmd1.CommandTimeout = 600
Regards,
Mark
Free Windows Admin Tool Kit Click here and download it now
June 10th, 2010 3:55pm
This is awesome.
Thanks for sharing, Mark!
I will add this to the main script.
Cheers,
Markus
Markus Vilcinskas, Knowledge Engineer, Microsoft Corporation
June 10th, 2010 7:27pm