Tuesday, October 11

BizTalk Server 2010 Automated Backup and Restore Script - PowerShell 2.0

Following on from my first post in this series,  this set of scripts uses the same ideology to create a snapshot of the BizTalk Server Instance before a new deployment script is executed. In the event of deployment failure, the restore script uses the snapshot to restore the server to it's previous state.

Working with the brilliant BizTalk Powershell Provider from codeplex (http://psbiztalk.codeplex.com/), the script uses the BTSCatalogExplorer Class of the Microsoft.BizTalk.ExplorerOm interface to get the BizTalk server applications currently installed on the server, and backs up the BizTalk Server instance

For the sake of clarity and brevity, I have omitted backing up of policies, but that could be easily added with a few extra lines of code. Also, because of my ASP.Net web development development background, I like clearly detailed layouts. So I have added a lot of colouring and spacing to make the logs easier to troubleshoot. These are not compulsory

If you haven't read the previous post, I suggest you do so, as that will make what I am doing here much clearer

This script will be used to backup all non-default, non-microsoft bizTalk applications present on the server. In this scneario, I have once again worked with the canonical CommonArtifacts system described in the last post. I am assuming that the company in question names it's shared applications by adding the word 'Common' into their naming conventions. So you could have department.CommonArtifacts, Department2.CommonArtifacts etc. These will need to be identified and restored first in the restore script

The folder structure is as follows:
D:\BizTalk\RollBackInstance\ is the source folder

All applications and their artifacts are stored in application folders created within child folders of the source folder
so once backed up, we will have:
D:\BizTalk\RollBackInstance\bindings\MyApps.BizTalk.Application2\D:\BizTalk\RollBackInstance\msis\MyApps.BizTalk.Application2\
D:\BizTalk\RollBackInstance\resources\MyApps.BizTalk.Application2\

and so on...

We have:
1. BackUp.bat script which calls the backup process
2. LaunchRollBack.bat script which calls the restore process
3. Functions.ps1 script which contains all the funcitons used for the processes
4. create_rollback.ps1 script which creates the backup folders
5. initiate_rollback.ps1 script which implements the restore process

The folder structure for the scripts is similar to the one used in my last post

Create folder structures as shown below:

Create the folders
D:\BizTalk\RollBackInstance\msis\
D:\BizTalk\RollBackInstance\bindings\
D:\BizTalk\RollBackInstance\logs\rollbacklogs
D:\BizTalk\RollBackInstance\scripts\
D:\BizTalk\RollBackInstance\configs\RedCross (optional, for copying the current BizTalk config file)



In the scripts folder, create the files create_rollback.ps1, initiate_rollback.ps1 and Functions.ps1 as follows



FILE 1
functions.ps1: -  
checks that the environment settings file exists and creates one if it does not exist
declares the functions to be used from the ExplorerOM dll
loads the BizTalk.Powershell.Extensions

- this file could be extended easily to remove and add policies, pipeline components, functoids etc

there are two main functions to note in this file,
CreateApplicationCatalogs which lists all applications in the BizTalk server instance, creates folders for each application found, exports the msi and bindings for each application into the new folders and creates a list of all resources found in each application

RestoreApplicationCatalogs which has two parts:
It first takes a 3rd-level backup of all msis found in BizTalk during the restore process and stored them in a folder called RedCross (some humour here),checks for common applications, stops all applications whose names do not start with 'BizTalk' or 'Microsoft' (so applications like Microsoft.Practices.ESB and BizTalk Applicaiton 1 are not affected), stops and removes all other applications, removing the common applications last 

In part 2, it searches the backup folder structure, counts the number of applications found, checks for common applications and installs them first, then installs all other applications and restarts all host instances

Functions.ps1

# By Stephen Omotomilola 03/02/2010
# Functions for BizTalk rollback section added
# Functions for BizTalk (some taken from the ESB Toolkit sample installation scripts)

# Get Server settings 
($env:USERDOMAIN -eq "MyCompanyDEV")
    {
    $inputFileRelativePath = "\\SharedComputerdev\Bank\BizTalkServerSettings\"
    }
if ($env:USERDOMAIN -eq "MyCompanyTEST")
    {
     $inputFileRelativePath = "
\\SharedComputertest\Bank\BizTalkServerSettings\"    }
    }


$inputFile = $inputFilerelativePath + "SetInputs-" + $env:COMPUTERNAME + ".xml"
if (test-path -path $inputFile)
    {
        Write-Host $inputFile  "found" -Separator " "  -BackgroundColor Green -ForegroundColor White
    }
Else
    {
        Write-Host $inputFile  "does not exist" -Separator " "  -BackgroundColor Red -ForegroundColor White
        Return
    }   


# Set export folders $resExpPath = ".\resources"
$policiesExpPath = ".\policies"


$xmlinput = [xml] (get-content $inputFile)   
   
# Get the top node$item = $xmlinput.BTS2010Config


# Read the parameters we want  $BTSInstallPath = $item.BTS2010InstallationPath
$ESBToolkitPath = $item.ESBToolkitInstallationPath
$btsConnectionString = $item.BTSConnectionString
$btsDBServerName = $item.BTSDBServerName
$btsDBName = $item.BTSDBName


# Colour for sections headers$sectHeadColour = "Gray"
$sectHeadColourALLGo = "Black"
$sectBackColourAllGo = "Green"
$sectBackColourIsOK = "Yellow"
$sectBackColourToDo = "Yellow"


if ($BTSInstallPath.EndsWith("\"))
{
 $BTSInstallPath = $BTSInstallPath.Substring(0, $BTSInstallPath.Length - 1)
}

if ($ESBToolkitPath.EndsWith("\"))
{
 $ESBToolkitPath = $ESBToolkitPath.Substring(0, $ESBToolkitPath.Length - 1)
}

$RulesDeployerPath = $ESBToolkitPath + "\bin\Microsoft.Practices.ESB.RulesDeployer.exe"
$ESBImportUtilPath = $ESBToolkitPath + "\bin\EsbImportUtil.exe"


# Loads the commands for the http://psbiztalk.codeplex.com/ add in
Write-Host "Loading the Powershell Biztalk Extensions"
$snapin = Get-PSSnapin | Where-Object {$_.Name -eq 'BizTalkFactory.PowerShell.Extensions'}
if ($snapin -eq $null)
    {
        $InitializeDefaultBTSDrive = $false
        Add-PSSnapin –Name BizTalkFactory.PowerShell.Extensions
  New-PSDrive -Name BizTalk -PSProvider BizTalk -ROOT BizTalk:\ -Instance $btsDBServerName -Database $btsDBName
    }


Function Biztalk: { Set-Location Biztalk: }
Function Biztalk:\ { Set-Location Biztalk:\ }


Write-Host "Finished Loading the Powershell Biztalk Extensions"

if ($BTSInstallPath -eq $null)
    {
        Write-Host "Cannot find BizTalk Install Path, check server and correct settings" -BackgroundColor Red -ForegroundColor White
        Return
    }
    Else
    {
        Write-Host "BizTalk Install Path" $BTSInstallPath -Separator `t
    }

   
if ($btsConnectionString -eq $null)
    {
        Write-Host "Cannot find BTS connection string, check server and correct settings" -BackgroundColor $sectHeadColourALLGo -ForegroundColor $sectHeadColour
        Return
    }
Else
    {
        Write-Host "BizTalk connection string" $btsConnectionString -Separator `t
    }

function GetBTSInstallPath
{
 $BTSInstallPath
}   

function GetbtsDBServerName
{
    $btsDBServerName
}

#Creating BTS Applications
function CreateBTSApplication
{
 param([string]$appName, [string]$logFile)
   
    Write-Host "Create Application" $appName -Separator `t
   
    [System.Reflection.Assembly]::LoadFrom($BTSInstallPath +"\Developer Tools\Microsoft.BizTalk.ExplorerOM.dll") | Out-Null

 $exp = New-Object Microsoft.BizTalk.ExplorerOM.BtsCatalogExplorer
    $exp.Applications
   
    Write-Host $exp
 $exp.ConnectionString = $btsConnectionString
 $app = $exp.Applications[$appName]

 if($app -eq $null)
 {
  Write-Output "Creating BizTalk Application "$appName 
  $returnCode = (BTSTask.exe AddApp /A:$appName)

  if ($LASTEXITCODE -eq 0)
  {
   Write-Host "$appname application created sucessfully"
  }
  Else
  {
   Write-Host "Create application $appname failed - review log file at $logFile" -BackgroundColor Red -ForegroundColor White
   $returnCode | Out-File $logFile
  }
 }
 else
 {
  Write-Host "Application " $appName " exists"
 }
}

#Removing BTS Applications
function RemoveBTSApplication
{
 param([string]$appName, [string]$logfile)
 Write-Host "Removing BTS Application " + $appName
 $returnCode =(BTSTask.exe RemoveApp /A:$appName)

 if ($LASTEXITCODE -eq 0)
 {
  Write-Host "$appname application removed sucessfully"
 }
 Else
 {
  Write-Host "Remove application $appname failed - review log file at $logFile" -BackgroundColor Red -ForegroundColor White
  $returnCode | Out-File $logFile
 }
}

#Removing BTS Resources
function RemoveBTSResource
{
 param([string]$appName, [string]$resource, [string]$logfile)
 Write-Output "Removing BTS Resource "+ $resource
 $returnCode =(BTSTask.exe RemoveResource  /A:$appName /L$resource)

 if ($LASTEXITCODE -eq 0)
 {
  Write-Host "$resource removed sucessfully"
 }
 Else
 {
  Write-Host "Remove resource $resource failed - review log file at $logFile" -BackgroundColor Red -ForegroundColor White
  $returnCode | Out-File $logFile
 }
}

#Importing BTS msi
function ImportBTSApplication
{
    param([string]$appName, [string]$msiPath, [string] $logFile)
    Write-Host "Importing $appName Application"
    $returnCode = (BTSTask.exe ImportApp -Package:$msiPath -ApplicationName:$appname -Overwrite)

 if ($LASTEXITCODE -eq 0)
 {
  Write-Host "$appname application imported sucessfully"
 }
 Else
 {
  Write-Host "$appname application import failed - review log file at $logFile" -BackgroundColor Red -ForegroundColor White
  $returnCode | Out-File $logFile
 }
}

#Importing BTS bindings
function ImportBinding
{
 param([string]$appName, [string]$bindingFilePath, [string]$logFile)
 # BTS Task
 BTSTask.exe ImportBindings  /A:$appName /So:$bindingFilePath

 if ($LASTEXITCODE -eq 0)
 {
  Write-Host "$appname binding imported sucessfully"
 }
 Else
 {
  Write-Host "$appname binding import failed - review log file at $logFile" -BackgroundColor Red -ForegroundColor White
  $returnCode | Out-File $logFile
 }
}

# ..................................................
#Specific Backup and Rollback Section Commands

#Backup Creation Process
function CreateApplicationCatalogs
{
 param([string]$mPath, [string]$bPath, [string]$lPath)

 Write-Host "Taking BizTalk Snapshot"
    Write-Host ""
 Write-Host ""
    [System.Reflection.Assembly]::LoadFrom($BTSInstallPath +"\Developer Tools\Microsoft.BizTalk.ExplorerOM.dll") | Out-Null

 $exp = New-Object Microsoft.BizTalk.ExplorerOM.BtsCatalogExplorer
    $exp.Applications
   
    $exp.ConnectionString = $btsConnectionString

#=== Loop through applications in the catalog ===#    $Expcount = $exp.Applications.Count
 $FirstExpcount = $Expcount
 Write-Host "$Expcount Applications found on " $btsDBServerName -ForegroundColor $sectHeadColourALLGo -BackgroundColor $sectBackColourAllGo

 foreach($Expa in $exp.Applications)
    {

 $NewExpapp = $Expa.Name

 if ($NewExpapp.StartsWith("BizTalk") -or $NewExpapp.StartsWith("Microsoft"))
    {     
   $Expcount = $Expcount-1
    }
 }
   
    Write-Host "$Expcount Relevant (non-default) Applications found out of $FirstExpcount on " $btsDBServerName -ForegroundColor $sectHeadColourALLGo -BackgroundColor $sectBackColourAllGo
    Write-Host "......................................." -ForegroundColor $sectBackColourIsOK
    Write-Host ""
    Write-Host "Creating backup..."
    Write-Host ""
    Write-Host ""

    $Expcountb = 0
    foreach($Expapp in $exp.Applications)
    {
     
    #Count Apps whilst Ignoring BizTalk Default Apps    $NewExpapp = $Expapp.Name
    if (!($NewExpapp.StartsWith("BizTalk") -or $NewExpapp.StartsWith("Microsoft")))
    {
    $Expcountb = $Expcountb-1
    $ExpCountUp = 0-$Expcountb
    Write-Host "......................................." -ForegroundColor $sectBackColourIsOK
    Write-Host $ExpcountUp ": Now working on " $NewExpapp " Application" -ForegroundColor $sectHeadColourALLGo -BackgroundColor $sectBackColourAllGo
    Write-Host "......................................." -ForegroundColor $sectBackColourIsOK
    Write-Host "Creating backup..."
       
       #Check for and create application folder    if (!(Test-Path -path $mPath\$NewExpapp\))
          {
              Write-Host "Application folder not found"
     Write-Host ""
     Write-Host ""
     Write-Host "Task 1 - Create Application Folder" -ForegroundColor $sectBackColourIsOK
     New-Item $mPath\$NewExpapp\ -type directory
              if (Test-Path -path $mPath\$NewExpapp\)
              {
                Write-Host "Task 1 Successful - Create Application Folder" -ForegroundColor $sectBackColourIsOK
    Write-Host "$mPath\$NewExpapp\"  -ForegroundColor $sectBackColourIsOK
    Write-Host "folder successfully created" -ForegroundColor $sectHeadColourALLGo -BackgroundColor $sectBackColourAllGo  
              }
          }
    Else
    {
        Write-Host "Application folder found"
     Write-Host ""
     Write-Host ""
     Write-Host "Task 1 - Create Application Folder: Not needed" -ForegroundColor $sectBackColourIsOK
     Write-Host "Moving on to Task 2 - Export Application msi" -ForegroundColor $sectBackColourIsOK
    }
   
    #Export Application msi    Write-Host ""
    Write-Host ""
    Write-Host ""
    Write-Host "Task 2 - Export Application msi" -ForegroundColor $sectBackColourIsOK
    ExportBTSApplication $NewExpapp "$mPath\$NewExpapp\$NewExpapp.msi" "$lPath\msiexportlogs\ExportApp_$NewExpapp.log"
   
    #List Application Resources for cross-checking    Write-Host ""
    Write-Host "Task 3 - Record Application Resources" -ForegroundColor $sectBackColourIsOK
    ListAppResources $NewExpapp "$mPath\$NewExpapp\resources\$NewExpapp.Resources.xml" "$lPath\resource_manifestlogs\AppResources_$NewExpapp.log"
   
    #Export bindings    Write-Host ""
    Write-Host "Task 4 (Final Task) - Export Application Bindings" -ForegroundColor $sectBackColourIsOK
    ExportBinding $NewExpapp "$bPath\$NewExpapp\$NewExpapp.bindinginfo.xml" "$lPath\bindings_xportlogs\ExportBindings_$NewExpapp.log"
       }   
    }
}

#Restore Process
function RestoreApplicationCatalogs
{
 param([string]$mPath, [string]$bPath, [string]$lPath)

 [string[]]$NonCommonApps = New-Object System.Collections.ArrayList
 [string[]]$AllCommonApps = New-Object System.Collections.ArrayList

 Write-Host "Restoring From BizTalk Snapshot"
    Write-Host ""
 Write-Host ""
    [System.Reflection.Assembly]::LoadFrom($BTSInstallPath +"\Developer Tools\Microsoft.BizTalk.ExplorerOM.dll") | Out-Null

 $exp = New-Object Microsoft.BizTalk.ExplorerOM.BtsCatalogExplorer
    $exp.Applications
   
    $exp.ConnectionString = $btsConnectionString

#=== Loop through and remove applications in BTS ===#
#=== Loop through and make a list of applications in BTS ===#    $Expcount = $exp.Applications.Count
 $FirstExpcount = $Expcount
 Write-Host "$Expcount Applications found on " $btsDBServerName -ForegroundColor $sectHeadColourALLGo -BackgroundColor $sectBackColourAllGo
 $CommonExists = "No"

 foreach($Expa in $exp.Applications)
    {
     $NewExpapp = $Expa.Name

  #Add applicastion name to list  if (!($NewExpapp -Like "*Common*") -and !($NewExpapp.StartsWith("BizTalk") -or $NewExpapp.StartsWith("Microsoft")))
    {
  $NonCommonApps = $NonCommonApps + $NewExpapp
    }

#Check for Common (shared) applications
 if ($NewExpapp -Like "*Common*")
    {
      $AllCommonApps = $AllCommonApps + $NewExpapp
   $CommonExists = "Yes"
    }
   
    #Count Apps whilst Ignoring BizTalk Default Apps   
    if ($NewExpapp.StartsWith("BizTalk") -or $NewExpapp.StartsWith("Microsoft"))
    {     
   $Expcount = $Expcount-1
    }
 }
    Write-Host "$Expcount Relevant (non-default) Applications found out of $FirstExpcount on " $btsDBServerName -ForegroundColor $sectHeadColourALLGo -BackgroundColor $sectBackColourAllGo
    Write-Host "......................................." -ForegroundColor $sectBackColourIsOK
    Write-Host ""
    Write-Host ""
    $Expcommoncount = $AllCommonApps.Count
    Write-Host "$Expcommoncount Common Applications found on " $btsDBServerName -ForegroundColor $sectHeadColourALLGo -BackgroundColor $sectBackColourAllGo
    Write-Host "......................................." -ForegroundColor $sectBackColourIsOK
    Write-Host ""
    Write-Host "Removing All Relevant Applications..."
    Write-Host ""
    Write-Host ""

    $Expcountb = 0

#Now actually remove relevant apps

 #Remove non-common apps first
    foreach($noncommon in $NonCommonApps)
 {
          
    $NewExpapp = $noncommon  
    $Expcountb = $Expcountb-1
    $ExpCountUp = 0-$Expcountb
    Write-Host "......................................." -ForegroundColor $sectBackColourIsOK
    Write-Host "Now working on " $NewExpapp " Application" -ForegroundColor $sectHeadColourALLGo -BackgroundColor $sectBackColourAllGo
    Write-Host "......................................." -ForegroundColor $sectBackColourIsOK
    Write-Host "Stopping Application..."
              
    #Stop Application    Write-Host ""
    Write-Host ""
    Write-Host ""
    Write-Host "Task 1 - Stop Application" -ForegroundColor $sectBackColourIsOK
    ExportBTSApplication $NewExpapp "$mPath\$NewExpapp\RedCross\msis\$NewExpapp.msi" "$lPath\rollbacklogs\ExportApp_$NewExpapp.log"
       ExportBinding $NewExpapp "$mPath\$NewExpapp\RedCross\bindings\$NewExpapp.bindinginfo.xml" "$lPath\rollbacklogs\ExportBindings_$NewExpapp.log"
         StopBTSApplication $NewExpapp "$lPath\rollbacklogs\StopApp_$NewExpapp.log"
   
    #Remove Application    Write-Host ""
    Write-Host "Task 2 - Remove Application" -ForegroundColor $sectBackColourIsOK
    ListAppResources $NewExpapp "$mPath\$NewExpapp\RedCross\resources\$NewExpapp.Resources.xml" "$lPath\rollbacklogs\AppResources_$NewExpapp.log"
       RemoveBTSApplication $NewExpapp "$lPath\rollbacklogs\RemoveApp_$NewExpapp.log"
             Write-Host ""
       Write-Host ""
  } 
   
  #Now remove Common Apps  if ($CommonExists -eq "Yes")
  {
  foreach($Commonapp in $AllCommonApps)
     {
   
    Write-Host "......................................." -ForegroundColor $sectBackColourIsOK
    Write-Host "Now working on " + $Commonapp + " Application" -ForegroundColor $sectHeadColourALLGo -BackgroundColor $sectBackColourAllGo
    Write-Host "......................................." -ForegroundColor $sectBackColourIsOK
    Write-Host "Stopping Application..."
   
      #Stop Application    Write-Host ""
    Write-Host ""
    Write-Host ""
    Write-Host "Task 1 - Stop Application" -ForegroundColor $sectBackColourIsOK
    ExportBTSApplication $Commonapp "$mPath\$Commonapp\RedCross\msis\$Commonapp.msi" "$lPath\rollbacklogs\ExportApp_$Commonapp.log"
       ExportBinding $Commonapp "$mPath\$Commonapp\RedCross\bindings\$Commonapp.bindinginfo.xml" "$lPath\rollbacklogs\ExportBindings_$Commonapp.log"
         StopBTSApplication $Commonapp "$lPath\rollbacklogs\StopApp_$Commonapp.log"
   
    #Remove Application    Write-Host ""
    Write-Host "Task 2 - Remove Application" -ForegroundColor $sectBackColourIsOK
    ListAppResources $Commonapp "$mPath\$Commonapp\RedCross\resources\$Commonapp.Resources.xml" "$lPath\rollbacklogs\AppResources_$Commonapp.log"
       RemoveBTSApplication $Commonapp "$lPath\rollbacklogs\RemoveApp_$Commonapp.log"
    Write-Host ""
       Write-Host ""   
     }
 
  }
 
  # Restart Host Instances    Write-Host ""
    Write-Host "Task - Restart HostInstances" -ForegroundColor $sectBackColourIsOK
          RestartHostInstances $lPath + "\rollbacklogs\RestartHostinstancesa.log"
       Write-Host ""
    Write-Host ""
    Write-Host "......................................." -ForegroundColor Green
    Write-Host "All Relevant Applications Successfully Removed" -ForegroundColor Yellow
    Write-Host "......................................." -ForegroundColor Green
    Write-Host ""
    Write-Host ""


#PART 2  
#=== Loop through and create applications from the backup directories ===#
 if (!(Test-Path -path $mPath))
    {
   Write-Host ""
   Write-Host ""
   Write-Host "......................................." -ForegroundColor Red
   Write-Host "Error!!! BackUp Directory Not Found - $mPath" -ForegroundColor Red
   Write-Host "Please contact an administrator - Exiting..." -ForegroundColor White
   Write-Host "......................................." -ForegroundColor Red
   Write-Host ""
   Write-Host ""
   Exit
 }
 Else
 {
   Write-Host "......................................." -ForegroundColor Yellow
   Write-Host "Found - $mPath" -ForegroundColor White
   Write-Host "......................................." -ForegroundColor Yellow
   Write-Host ""
   Write-Host ""
   $dirs = get-childitem $mPath | Where {$_.psIsContainer -eq $true -and !($_.name -Like "*Common*")}
   $dcounted = $dirs.Count
   Write-Host "Now Restoring From RollBack Applications..."
   Write-Host ""
   Write-Host ""
   Write-Host "Found $dcounted non-common application folders" -ForegroundColor White
   Write-Host "......................................." -ForegroundColor Yellow
   Write-Host ""
        
   [string[]]$CommonApps = get-childitem $mPath | where {$_.name -Like "*Common*"}
      $dcounted2 = $CommonApps.Count
      Write-Host "Found $dcounted2 common application folders" -ForegroundColor White
   Write-Host "......................................." -ForegroundColor Yellow
  
#  Re-Installing From Folders   #Restore Applications
     #Check for Common Artifacts and install first if found
  $counting = 0
  If ($CommonApps)
  {
      foreach($DFName in $CommonApps)
         {    
       Write-Host "Installing (shared) common artifacts first ..." -ForegroundColor $sectHeadColourALLGo -BackgroundColor $sectBackColourAllGo
    Write-Host "......................................." -ForegroundColor $sectBackColourIsOK
    $counting = $counting + 1
       $AppPath = $mPath + "\" + $DFName + "\" + $DFName + ".msi"
       $AppBingdingsPath = $bPath + "\" + $DFName + "\" + $DFName + ".bindinginfo.xml"
  
       Write-Host ""
             Write-Host ""
             Write-Host "......................................." -ForegroundColor $sectBackColourIsOK
          Write-Host $counting ": Now restoring " $DFName " Application" -ForegroundColor $sectHeadColourALLGo -BackgroundColor $sectBackColourAllGo
          Write-Host "......................................." -ForegroundColor $sectBackColourIsOK

       Write-Host "Creating Application..."
              
       #Create Application       Write-Host ""
       Write-Host ""
       Write-Host ""
       Write-Host "Task 1 - Create Application" -ForegroundColor $sectBackColourIsOK
       CreateBTSApplication $DFName "$lPath\rollbacklogs\CreateApplication_$DFName.log"
         
       #Import Application             Write-Host ""
       Write-Host "Task 2 - Import Application" -ForegroundColor $sectBackColourIsOK
    $logFile = $lPath + "\rollbacklogs\ImportApplication_$DFName.log"
       ImportBTSApplication $DFName $AppPath $logFile   
   
       #Import Bindings             Write-Host ""
       Write-Host "Task 3 - Import Application Bindings" -ForegroundColor $sectBackColourIsOK
    $logFile = $lPath + "\rollbacklogs\ImportBindings_$DFName.log"
       ImportBinding $DFName $AppBingdingsPath $logFile
    
 #Install Application             Write-Host ""
       Write-Host "Task 4 - Install Application" -ForegroundColor $sectBackColourIsOK
       $msiFile = $AppPath
             $logFile = $lPath + "\rollbacklogs\$DFName.msi.install.log"
             InstallMSI $AppPath $logFile
             # Restart Host Instances
       Write-Host ""
       Write-Host "Task 5 - Restart Host Instances" -ForegroundColor $sectBackColourIsOK
             RestartHostInstances $lPath + "\rollbacklogs\RestartHostinstances.log"
         
       #Start Application             Write-Host ""
       Write-Host "Task 6 - Start Application" -ForegroundColor $sectBackColourIsOK
             StartBTSApplication $DFName "$lPath\rollbacklogs\StartApplication_$DFName.log"      
  
   }
  } #end if check for common atifacts
   #Run loop again to do non-common apps   foreach($DFName in $dirs)
         {      
         
       $counting = $counting + 1
       $AppPath = $mPath + "\" + $DFName + "\" + $DFName + ".msi"
       $AppBingdingsPath = $bPath + "\" + $DFName + "\" + $DFName + ".bindinginfo.xml"
  
       Write-Host ""
             Write-Host ""
             Write-Host "......................................." -ForegroundColor $sectBackColourIsOK
          Write-Host $counting: Now restoring $DFName Application -ForegroundColor $sectHeadColourALLGo -BackgroundColor $sectBackColourAllGo
          Write-Host "......................................." -ForegroundColor $sectBackColourIsOK
       Write-Host ""
             Write-Host ""
       Write-Host "Creating Application..."
              
       #Create Application
       Write-Host ""
       Write-Host ""
       Write-Host "Task 1 - Create Application" -ForegroundColor $sectBackColourIsOK
    $logFile = $lPath + "\rollbacklogs\CreateApplication_$DFName.log"
       CreateBTSApplication $DFName $logFile
         
       #Import Application             Write-Host ""
       Write-Host "Task 2 - Import Application" -ForegroundColor $sectBackColourIsOK
    $logFile = $lPath + "\rollbacklogs\ImportApplication_$DFName.log"
       ImportBTSApplication $DFName $AppPath $logFile   
   
       #Import Bindings             Write-Host ""
       Write-Host "Task 3 - Import Application Bindings" -ForegroundColor $sectBackColourIsOK
    $logFile = $lPath + "\rollbacklogs\ImportBindings_$DFName.log"
       ImportBinding $DFName $AppBingdingsPath $logFile
        
#Install Application             Write-Host ""
       Write-Host "Task 4 - Install Application" -ForegroundColor $sectBackColourIsOK
       $msiFile = $AppPath
             $logFile = $lPath + "\rollbacklogs\$DFName.msi.install.log"
             InstallMSI $AppPath $logFile

     # Restart Host Instances       Write-Host ""
       Write-Host "Task 5 - Restart HostInstances" -ForegroundColor $sectBackColourIsOK
             RestartHostInstances $lPath + "\rollbacklogs\RestartHostinstances.log"
         
       #Start Application             Write-Host ""
       Write-Host "Task 6 - Start Application" -ForegroundColor $sectBackColourIsOK
    $logFile = $lPath + "\rollbacklogs\StartApplication_$DFName.log"
             StartBTSApplication $DFName $logFile
             
   }   
  
 } #end if check for installaiton folder existence
}

#Exporting msi
function ExportBTSApplication
{
    param([string]$appName, [string]$msiExpPathName, [string] $logFile)
    Write-Host "Exporting $appName Application"
 Write-Host ""
    $returnCode = (BTSTask.exe ExportApp -ApplicationName:$appName -Package:$msiExpPathName)

 if ($LASTEXITCODE -eq 0)
 {
  Write-Host "Task Successful - Export Application msi" -ForegroundColor $sectBackColourIsOK
  Write-Host "$appName application exported sucessfully" -ForegroundColor $sectHeadColourALLGo -BackgroundColor $sectBackColourAllGo
  Write-Host ""
  Write-Host ""
     Write-Host ""
 }
 Else
 {
  Write-Host "Task Failure! - Export Application msi"  -ForegroundColor Red
  Write-Host "$appName application export failed - review log file at $logFile" -BackgroundColor Red -ForegroundColor White
  Write-Host ""
  Write-Host ""
     Write-Host ""
  $returnCode | Out-File $logFile
 }
}

#Exporting BTS application bindings
function ExportBinding
{
 param([string]$appName, [string]$bindingFilePath, [string]$logFile)
    Write-Host "Exporting bindings for $appName"
 Write-Host ""
 # BTS Task
 BTSTask.exe ExportBindings -Destination:$bindingFilePath -ApplicationName:$appName
 if ($LASTEXITCODE -eq 0)
 {
  Write-Host "Task Successful - Export Application Bindings" -ForegroundColor $sectBackColourIsOK
  Write-Host "$appname bindings exported sucessfully" -ForegroundColor $sectHeadColourALLGo -BackgroundColor $sectBackColourAllGo
  Write-Host ""
  Write-Host ""
     Write-Host ""
 }
 Else
 {
  Write-Host "Task Failure! - Export Application Bindings"  -ForegroundColor Red
  Write-Host "$appname bindings export failed - review log file at $logFile" -BackgroundColor Red -ForegroundColor White
  Write-Host ""
  Write-Host ""
     Write-Host ""
  $returnCode | Out-File $logFile
 }
}

#List resources found in BTS application
function ListAppResources
{
 param([string]$appName, [string]$ResFilePath, [string]$logFile)
    Write-Host "Recording Resources for $appName"
 Write-Host ""
 # List Application Resources to file
 BTSTask.exe ListApp -ApplicationName:$appName -ResourceSpec:$ResFilePath

 if ($LASTEXITCODE -eq 0)
 {
  Write-Host "$appname Resources listed sucessfully into file" -ForegroundColor $sectBackColourIsOK
  Write-Host $ResFilePath -ForegroundColor $sectHeadColourALLGo -BackgroundColor $sectBackColourAllGo
  Write-Host ""
  Write-Host ""
     Write-Host ""
 }
 Else
 {
  Write-Host "Task Failure! (Not Major) - Record Application Resources"  -ForegroundColor RedWrite-Host
  Write-Host "$appname Resources listing failed - review log file at $logFile" -BackgroundColor Red -ForegroundColor White
  Write-Host ""
  Write-Host ""
     Write-Host ""
  $returnCode | Out-File $logFile
 }
}
# .................................................................
# End Rollback Section Commands


#Installing a BTS msi
function InstallMSI
{
    param([string] $msiPath, [string] $logFilePath)
    $parameters = "-qr -i " + $msiPath + " -le " + $logFilePath
    $installStatement = [System.Diagnostics.Process]::Start("msiexec", $parameters)
    $installStatement.WaitForExit()
}

function UninstallMSI
{
    param([string] $msiPath, [string] $logFilePath)
    $parameters = "-qr -x " + $msiPath + " -le " + $logFilePath
    $installStatement = [System.Diagnostics.Process]::Start("msiexec", $parameters)
    $installStatement.WaitForExit()
}

#starting a BTS Application
function StartBTSApplication
{
 param([string]$appName, [string]$logfile)
 cd BizTalk:\Applications
 Write-Host "Starting BTS Application " + $appName
 Start-Application -Path $appName -StartOption StartAll
}

#Stopping BTs Application
function StopBTSApplication
{
 param([string]$appName, [string]$logfile)
 cd BizTalk:\Applications
 Write-Host "Stopping BTS Application " + $appName
 Stop-Application -Path $appName -StopOption StopAll
}

#Restarting host instances
function RestartHostInstances
{
 param([string]$logfile)

 cd BizTalk:\Applications
 Write-Output "Restarting Host Instances......"
 Set-Location '\Platform Settings\Host Instances'
 Get-ChildItem | `
 Where-Object { $_.ServiceState -eq 'Running' } | `
    Restart-HostInstance
}
FILE 2
create_rollback.ps1: -  
sets the correct folder paths, backs up the BTs config file and calls the backup process 


create_rollback.ps1
#  Create Rollback script for BizTalk installations...
#  Stephen Omotomilola 06-01-2010

# This must be called from a batch file
param
(
    [string]$launchedFromBatch = $(throw '- This script should be launched from a batch file as it relies on relative paths')
)

# Call BTSFunctions file. .\Scripts\Functions.ps1

#Get current location to use as reference
[string]$path = Get-Location
$applicationPath = $path + "\Applications"
$scriptsPath = $path + "\Scripts"
$backupConfigPathExp = $path + "\configs\"
$msiExpPath = $path + "\msis"
$bindingsExpPath = $path + "\bindings"
$applogExpPath = $path + "\logs"

Write-Host "BTS Installation Rollback Creation Package"
Write-Host ""
Write-Host ""

$Error.Clear()
Write-Host "Now Backing Up BTS Snapshot for RollBack  " -Separator `t
CreateApplicationCatalogs $msiExpPath $bindingsExpPath $applogExpPath

# Backup the BTS config file$newBtsFile = $backupConfigPathExp + "\BTSNTSvc64.exe.config"
$BTSInstallPath = GetBTSInstallPath
$existingBtsFile = $BTSInstallPath + "\BTSNTSvc64.exe.config"
Write-Host "Existing config  " $existingBtsFile -Separator `t
Write-Host ""
Write-Host ""
Write-Host "Backing up BTSNTSvc64.exe.config from " $existingBtsFile " to " $backupConfigPathExp
Copy-Item $existingBtsFile -destination $backupConfigPathExp -force
Write-Host ""
Write-Host ""

$a = Get-Date
Write-Host "BackUp Completed at $a"
Write-Host "To use this backup for a rollback, Double-Click on the LaunchRollBack.bat file"
Write-Host "`nPress any key to exit... Thank you"
$x = $host.UI.RawUI.ReadKey("NoEcho,IncludeKeyUp")

FILE 3
initiate_rollback.ps1: -  
sets the correct folder paths, restores the BTS server instance by calling the restore process 

 
initiate_rollback.ps1

#  Create Rollback script for BizTalk installations...
#  Stephen Omotomilola 06-01-2010

# This must be called from a batch fileparam
(
    [string]$launchedFromBatch = $(throw '- This script should be launched from a batch file as it relies on relative paths')
)


# Call BTSFunctions file. .\Scripts\Functions.ps1
[string]$path = Get-Location
$applicationPath = $path + "\Applications"
$scriptsPath = $path + "\Scripts"
$backupConfigPathExp = $path + "\configs\"
$msiExpPath = $path + "\msis"
$bindingsExpPath = $path + "\bindings"
$applogExpPath = $path + "\logs"

Write-Host "BTS Installation Rollback Creation Package"
Write-Host ""
Write-Host ""


$Error.Clear()
$a = Get-Date
Write-Host ""
Write-Host ""
Write-Host "Attempting To Intitiate RollBack Catalog at $a"
Write-Host ""
Write-Host ""
Write-Host "Warning: This RollBack Will Restore All BizTalk Applications To An Earlier Snapshot!!" -ForegroundColor White
Write-Host "..................................................." -ForegroundColor Red
Write-Host ""
Write-Host ""
Write-Host "You Need To Confirm To use This Rollback" -ForegroundColor White
Write-Host "`nPress any key to confirm or close this window to exit... Thank you"  -ForegroundColor Yellow
Write-Host "..................................................." -ForegroundColor Red
$x = $host.UI.RawUI.ReadKey("NoEcho,IncludeKeyUp")


#Start RollBack$BTSInstallPath = GetBTSInstallPath
$btsDBServerName = GetbtsDBServerName
$RedCross = $backupConfigPathExp + "\RedCross\"

Write-Host ""
Write-Host ""
Write-Host "Now Rollingback BizTalk Server" $btsDBServerName -Separator `t -ForegroundColor White
Write-Host "......................................." -ForegroundColor White
Write-Host ""


# RollBack the BTS config file$newBtsFile = $backupConfigPathExp + "\BTSNTSvc64.exe.config"
$existingBtsFile = $BTSInstallPath + "\BTSNTSvc64.exe.config"
Write-Host "Task - Replacing current BTS config BTSNTSvc64.exe.config with previous config"  -ForegroundColor $sectBackColourIsOK
Write-Host "from" $backupConfigPathExp -Separator `t  -ForegroundColor $sectBackColourIsOK
Write-Host "......................................." -ForegroundColor White

if (!(Test-Path -path $RedCross))
   {
     New-Item $RedCross -type directory
   }
  
Copy-Item $existingBtsFile -destination "$RedCross\BTSNTSvc64.exe.config" -force
Copy-Item $newBtsFile -destination $existingBtsFile -force
Write-Host "Task Successful - BizTalk Server Configuration Replaced" -ForegroundColor $sectHeadColourALLGo -BackgroundColor $sectBackColourAllGo
Write-Host ""
Write-Host ""


#Restore from catalogRestoreApplicationCatalogs $msiExpPath $bindingsExpPath $applogExpPath
$a = Get-Date
Write-Host ""
Write-Host ""
Write-Host "......................................." -ForegroundColor Green
Write-Host "RollBack Completed at $a" -ForegroundColor White
Write-Host "`nPress any key... Thank you" -ForegroundColor White
Write-Host "......................................." -ForegroundColor Green
Write-Host ""
Write-Host ""
$x = $host.UI.RawUI.ReadKey("NoEcho,IncludeKeyUp")


FILE 4
Backup.bat -  
Batch file to start off the backup process 


Backup.bat

@ECHO OFF
SETLOCAL
@TITLE -- Install BizTalk Solution
COLOR 02
FOR /F "tokens=2-4 delims=/ " %%i IN ('date /t') DO SET SHORTDATE=%%i-%%j-%%k
FOR /F "tokens=1-3 delims=: " %%i IN ('time /t') DO SET SHORTTIME=%%i-%%j%%k
SET LaunchedFromBAT=1

:START
:: Check for Powershell v2.0
ECHO - Checking for Powershell 2.0...
"%SYSTEMROOT%\sysWOW64\windowspowershell\v1.0\powershell.exe" $host.Version.Major | find "2" >nul
IF ERRORLEVEL 1 (
 COLOR 0C
 ECHO - This script requires PowerShell version 2.0!
 ECHO - Please uninstall v1.0, install v2.0, then re-run this script.
 COLOR
 pause
 EXIT
 )
ECHO - OK.

:: Get existing Powershell ExecutionPolicy
Echo Check Powershell Execution Policy
FOR /F "tokens=*" %%x in ('"%SYSTEMROOT%\sysWOW64\windowspowershell\v1.0\powershell.exe" Get-ExecutionPolicy') do (set ExecutionPolicy=%%x)
:: Set Bypass, in case we are running over a net share or UNC
IF NOT "%ExecutionPolicy%"=="Bypass" (
 ECHO - PS ExecutionPolicy is %ExecutionPolicy%, setting ExecutionPolicy to Bypass.
 "%SYSTEMROOT%\sysWOW64\windowspowershell\v1.0\powershell.exe" Set-ExecutionPolicy Bypass
 )

GOTO LAUNCHSCRIPT
:LAUNCHSCRIPT
Echo Calling \Scripts\create_rollback.ps1
"%SYSTEMROOT%\sysWOW64\windowspowershell\v1.0\powershell.exe" -command "& '%~dp0Scripts\create_rollback.ps1' '%LaunchedFromBAT%'"
GOTO END

:END
Echo All Done!
Echo Review the output and then press a key to close the window
pause
ENDLOCAL


7 comments:

  1. Very smooth solution. I can't seem to find the LaunchRollback.bat script though

    ReplyDelete
  2. Hmmm. you're right. I'll have to re-visit and add that when I have some time :)

    ReplyDelete
  3. Hi Stephen - very useful scripts. I'm very new to BizTalk and been only doing some administration. Due to company changes we have a requirement to build a new BT server and transfer the existing installation of BT to the new domain server. After installing vanilla BT on the new domain can I then use these scripts to export all the configs and then run the import script to transfer all the artifices or we have to do something more to make this happen? We will definitely have to change all the service accounts on the new server so will the import from the different domain work on the new BT server?
    Your advice would be really appreciated as I am very new to this and tasked with this.
    Thanks heaps,
    Anant

    ReplyDelete
  4. Hi Anant, I'm afraid the scripts are meant for a different purpose. they will not copy BizTalk environment setup information like service accounts and configuration information. They are meant to be used to move (deploy and backup) BizTalk applications into and out of an existing BizTalk instance that has already been set up and configured

    ReplyDelete
  5. Is it Possibel backing up a biztalk application
    msi, web, bindings all separate
    and execute it remotely

    ReplyDelete
  6. This comment has been removed by the author.

    ReplyDelete