In this sample, I have created a bat file which is used to automatically install BizTalk applications onto a BTS installation via powershell using the brilliant BizTalk Powershell Provider from codeplex (http://psbiztalk.codeplex.com/),. This script can be used for installing one application or for a full deployment of a suite of applications on the same server.
Next, i will post a sample which backs up the current BizTalk Server Applications and Restores if a deployment goes wrong
The scenario assumes the development domain (MyCompanyDEV) is different from the test domain (MyCompanyTEST) and therefore calls different environment variables depending on domains
A shared location will need to be created on a computer which is accessible from each domains. A folder on this computer will be used to store the settings files for each computer
file://sharedcomputerdev/Bank/BizTalkServerSettings/ for the dev domain
file://sharedcomputertest/Bank/BizTalkServerSettings/ for the test domain
Name the settings file after your installation computer and create a similar one (to the one below) in this location for every computer on which the installation scripts will be used
FILE 1
SetInputs-sampleinputs.xml
<?xml version="1.0" encoding="utf-8" ?>
<BTS2010Config>
<BTS2010InstallationPath>
C:\Program Files (x86)\Microsoft BizTalk Server 2010\
</BTS2010InstallationPath>
<ESBToolkitInstallationPath>
C:\Program Files (x86)\Microsoft BizTalk ESB Toolkit 2.1\
</ESBToolkitInstallationPath>
<BTSConnectionString>
server=<your bts server name>;database=BizTalkMgmtDb;Integrated Security=SSPI
</BTSConnectionString>
<BTSDBServerName>localhost</BTSDBServerName>
<BTSDBName>BizTalkMgmtDb</BTSDBName>
</BTS2010Config>
(We are assuming the computer running the script is called devcomputer101)
FILE 2
SetInputs-devcomputer101.xml
<?xml version="1.0" encoding="utf-8" ?>
<BTS2010Config>
<BTS2010InstallationPath>
C:\Program Files (x86)\Microsoft BizTalk Server 2010\
</BTS2010InstallationPath>
<ESBToolkitInstallationPath>
C:\Program Files (x86)\Microsoft BizTalk ESB Toolkit 2.1\
</ESBToolkitInstallationPath>
<BTSConnectionString>
server=<your bts server name>;database=BizTalkMgmtDb;Integrated Security=SSPI
</BTSConnectionString>
<BTSDBServerName>localhost</BTSDBServerName>
<BTSDBName>BizTalkMgmtDb</BTSDBName>
</BTS2010Config>
The bat file calls a script file (release.ps1) which contains the instructions for the deployment
The script file in turn calls a functions file which loads all the functions defined for the deployment tasks
This scripts have been written for powershell 2.0
The sample simulates a canonical scenario where there is an application (myapps.biztalk.commonartifacts) containing shared schemas used by 2 other applications. This commonartifacts application therefore needs to be installed first and removed last in any deployment scripts
After each application is installed, control comes back to the calling script for further user input - this step could be removed for full automation
The folder structure is as follows:
D:\BizTalk is the source folder
All applications and their artifacts are stored in an application folder within the source folder
so we have:
D:\BizTalk\MyApps.BizTalk.CommonArtifacts
D:\BizTalk\MyApps.BizTalk.Application2\
D:\BizTalk\MyApps.BizTalk.Application3\
Each application folder contains:
- a folder called applications which contains the msi file
- a folder called bindings which is further divided into two folders, MyCompanyDEV and MyCompanyTEST which contain the xml bindings configuration files for the dev and test domains respectively
- a folder called assemblies which contains required assemblies
- a folder called scripts which contains required scripts
Since we want to install the CommonArtifacts application first, we run install.bat from this application folder (D:\BizTalk\MyApps.BizTalk.CommonArtifacts\Install.bat). This will execute all the required deployment scripts and install all three applications one by one
FILE 3
Install.bat:
checks the powershell version
sets the executionpolicy
calls the script files to install each application
Install.bat
:: Copied from launch.bat for AutoSpInstaller
@ECHO OFF
SETLOCAL
@TITLE -- Install BizTalk Solution (s)
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
)
Echo.
Echo.
pause
GOTO LAUNCHSCRIPT1
::Launch myapps.biztalk.commonartifacts
:LAUNCHSCRIPT1
Echo Calling \Scripts\Release.ps1
"%SYSTEMROOT%\sysWOW64\windowspowershell\v1.0\powershell.exe" -command "& '%~dp0Scripts\Release.ps1' '%LaunchedFromBAT%'"GOTO END1
:END1
Echo Review the output and then press a key to move on to the next application
Echo MyApps.BizTalk.Application2
pause
GOTO LAUNCHSCRIPT2
::Launch MyApps.BizTalk.Application2
:LAUNCHSCRIPT2
Echo.
Echo.
Echo Calling Myapps.BizTalk.Application2\Scripts\Release.ps1
"%SYSTEMROOT%\sysWOW64\windowspowershell\v1.0\powershell.exe" -command "& '..\MyApps.BizTalk.Application2\Scripts\Release.ps1' '%LaunchedFromBAT%'"
GOTO END2
:END2
Echo Review the output and then press a key to move on to the next application
Echo MyApps.BizTalk.Application3
pause
GOTO LAUNCHSCRIPT3
::Launch MyApps.BizTalk.Application3
:LAUNCHSCRIPT3
Echo.
Echo.
Echo Calling MyApps.BizTalk.Application3\Scripts\Release.ps1
"%SYSTEMROOT%\sysWOW64\windowspowershell\v1.0\powershell.exe" -command "& '..\MyApps.BizTalk.Application3\Scripts\Release.ps1' '%LaunchedFromBAT%'"
GOTO END
:END
Echo All Done. Review the output and then press a key to end
pause
ENDLOCAL
FILE 4
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
Functions.ps1
# Functions for BizTalk (some taken from the ESB Toolkit sample installation scripts)
# Get Server settings
if ($env:USERDOMAIN -eq "MyCompanyDEV")
{
$inputFileRelativePath = "\\SharedComputerdev\Bank\BizTalkServerSettings\"
}
if ($env:USERDOMAIN -eq "MyCompanyTEST")
{
$inputFileRelativePath = "\\SharedComputertest\Bank\BizTalkServerSettings\" }
}
# Colour for sections headers
$sectHeadColour = "Gray"
$sectHeadColourALLGo = "Black"
$sectBackColourAllGo = "Green"
$sectBackColourIsOK = "Yellow"
$sectBackColourToDo = "Yellow"
Write-Host "Color Coding"
Write-Host "Good" -ForegroundColor $sectHeadColourALLGo -BackgroundColor $sectBackColourAllGo
Write-host "Ignore" -ForegroundColor $sectHeadColourALLGo -BackgroundColor $sectBackColourIsOK
Write-Host "Bad" -BackgroundColor Red -ForegroundColor White
Write-Host "`nChecking settings for $env:COMPUTERNAME" -ForegroundColor $sectHeadColour
#check for environment settings file
$inputFile = $inputFilerelativePath + "SetInputs-" + $env:COMPUTERNAME + ".xml"
if (test-path -path $inputFile)
{
Write-Host $inputFile "found" -Separator " "
Write-Host "`nExiting settings check process" -ForegroundColor $sectHeadColourALLGo -BackgroundColor $sectBackColourAllGo
}
Else
{
Write-Host $inputFile "does not exist" -Separator " " -ForegroundColor $sectHeadColourALLGo -BackgroundColor $sectBackColourAllGo
Write-Host "Computer name is $env:COMPUTERNAME" -ForegroundColor $sectHeadColour
Write-Host "`nCreating environment settings file for $env:COMPUTERNAME in $inputFileRelativePath" -ForegroundColor $sectHeadColour
Copy-Item $inputFileRelativePath\SetInputs-$sampleinput.xml $inputFileRelativePath\SetInputs-$env:COMPUTERNAME.xml
if (test-path -path $inputFile)
{
Write-Host "`nSettings file successfully created" -ForegroundColor $sectHeadColourALLGo -BackgroundColor $sectBackColourAllGo
}
}
#Read xml nodes from environments settings file
$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
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"
# Load the commands for the http://psbiztalk.codeplex.com/ add in
Write-Host "`nLoading the Powershell Biztalk Extensions" -ForegroundColor $sectHeadColour
$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" -ForegroundColor $sectHeadColourALLGo -BackgroundColor $sectBackColourAllGo
Write-Host "`nVariables" -ForegroundColor $sectHeadColour
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 ($ESBToolkitPath -eq $null)
{
Write-Host "Cannot find ESB Tookit Install Path, check server and correct settings" -BackgroundColor Red -ForegroundColor White
Return
}
Else
{
Write-Host "ESB Toolkit Install Path" $ESBToolkitPath -Separator `t
}
if ($RulesDeployerPath -eq $null)
{
Write-Host "Cannot find Rules Deployer Path, check server and correct settings" -BackgroundColor Red -ForegroundColor White
Return
}
Else
{
Write-Host "Rules Deployer Path" $RulesDeployerPath
}
if (test-path -path $RulesDeployerPath)
{
Write-Host $RulesDeployerPath "found" -Separator `t -ForegroundColor $sectHeadColourALLGo -BackgroundColor $sectBackColourAllGo
}
Else
{
Write-Host $RulesDeployerPath "does not exist" -Separator " " -BackgroundColor Red -ForegroundColor White
Return
}
if ($btsConnectionString -eq $null)
{
Write-Host "Cannot find BTS connection string, check server and correct settings" -BackgroundColor Red -ForegroundColor White
Return
}
Else
{
Write-Host "BizTalk connection string" $btsConnectionString -Separator `t -ForegroundColor $sectHeadColourALLGo -BackgroundColor $sectBackColourAllGo
}
function CreateBTSApplication
{
param([string]$appName, [string]$logFile)
Write-Host "`nCreating Application $appName" -ForegroundColor $sectHeadColour
[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" -ForegroundColor $sectHeadColourALLGo -BackgroundColor $sectBackColourAllGo
}
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"
}
}
function RemoveBTSApplication
{
param([string]$appName, [string]$logfile)
Write-Host "`nRemoving BTS Application $appName" -ForegroundColor $sectHeadColour
$returnCode =(BTSTask.exe RemoveApp /A:$appName)
if ($LASTEXITCODE -eq 0)
{
Write-Host "$appname application removed sucessfully" -ForegroundColor $sectHeadColourALLGo -BackgroundColor $sectBackColourAllGo
}
Else
{
Write-Host "Failure removing application $appname - review log file at $logFile" -ForegroundColor $sectHeadColourALLGo -BackgroundColor $sectBackColourIsOK
$returnCode | Out-File $logFile
}
}
function ImportBTSApplication
{
param([string]$appName, [string]$msiPath, [string] $logFile)
Write-Host "`nImporting $appName Application" -ForegroundColor $sectHeadColour
$returnCode = BTSTask.exe ImportApp -Package:$msiPath -ApplicationName:$appname -Overwrite
if ($LASTEXITCODE -eq 0)
{
Write-Host "$appname application imported sucessfully" -ForegroundColor $sectHeadColourALLGo -BackgroundColor $sectBackColourAllGo
}
Else
{
Write-Host "$appname application import failed - review log file at $logFile" -BackgroundColor Red -ForegroundColor White
$returnCode | Out-File $logFile
}
}
function ImportBindings
{
param([string]$appName, [string]$bindingFilePath, [string]$logFile)
Write-Host "`nImporting $appName Bindings" -ForegroundColor $sectHeadColour
BTSTask.exe ImportBindings /A:$appName /So:$bindingFilePath
if ($LASTEXITCODE -eq 0)
{
Write-Host "$appname binding imported sucessfully" -ForegroundColor $sectHeadColourALLGo -BackgroundColor $sectBackColourAllGo
}
Else
{
Write-Host "$appname binding import failed - review log file at $logFile" -BackgroundColor Red -ForegroundColor White
$returnCode | Out-File $logFile
}
}
function InstallMSI
{
param([string] $msiPath, [string] $logFilePath)
Write-Host "`nInstalling $appName MSI" -ForegroundColor $sectHeadColour
$parameters = "-qr -i " + $msiPath + " -lcwe+ " + $logFilePath
Write-Host "Parameters:" $parameters
$installStatement = [System.Diagnostics.Process]::Start("msiexec", $parameters)
$installStatement.WaitForExit()
Write-Host "Done" -ForegroundColor $sectHeadColourALLGo -BackgroundColor $sectBackColourAllGo
}
function UninstallMSI
{
param([string] $msiPath, [string] $logFilePath)
Write-Host "`nUninstalling $appName MSI" -ForegroundColor $sectHeadColour
$parameters = "-qr -x " + $msiPath + " -lcwe " + $logFilePath
Write-Host "Parameters:" $parameters
$installStatement = [System.Diagnostics.Process]::Start("msiexec", $parameters)
$installStatement.WaitForExit()
Write-Host "Done" -ForegroundColor $sectHeadColourALLGo -BackgroundColor $sectBackColourAllGo
}
function StartBTSApplication
{
param([string]$appName, [string]$logfile)
cd BizTalk:\Applications
Write-Host "`nStarting BTS Application $appName" -ForegroundColor $sectHeadColour
Start-Application -Path $appName -StartOption StartAll
}
function StopBTSApplication
{
param([string]$appName, [string]$logfile)
Write-Host "`nStopping BTS Application $appName" -ForegroundColor $sectHeadColour
cd BizTalk:\Applications
if (test-path -path $appName)
{
Stop-Application -Path $appName -StopOption StopAll
if ($LASTEXITCODE -eq 0)
{
Write-Host "$appname application stopped sucessfully" -ForegroundColor $sectHeadColourALLGo -BackgroundColor $sectBackColourAllGo
}
Else
{
Write-Host "Stopping $appname application failed - review log file at $logFile" -BackgroundColor Red -ForegroundColor White
$returnCode | Out-File $logFile
}
}
Else
{
Write-Host "$appname application does not exist - moving on..." -ForegroundColor $sectHeadColourALLGo -BackgroundColor $sectBackColourIsOK
}
}
function RestartHostInstances
{
param([string]$logfile)
Write-Host "`nRestarting Host Instances......" -ForegroundColor $sectHeadColour
cd BizTalk:\Applications
Set-Location '\Platform Settings\Host Instances'
Get-ChildItem | `
Where-Object { $_.ServiceState -eq 'Running' } | `
Restart-HostInstance
if ($LASTEXITCODE -eq 0)
{
Write-Host "Restarted host instances sucessfully" -ForegroundColor $sectHeadColourALLGo -BackgroundColor $sectBackColourAllGo
}
Else
{
Write-Host "Restarting host instances failed - review log file at $logFile" -BackgroundColor Red -ForegroundColor White
$returnCode | Out-File $logFile
}
}
function UnGacAssemblies
{
param([string[]]$assemblyNames, [string]$assemblyFolder, [string]$logFile)
[bool]$errors = 0
[string[]]$errorString = "GacAssemblies"
Write-Host "`nRemoving assemblies from GAC" -ForegroundColor $sectHeadColour
foreach ($assemblyName in $assemblyNames)
{
# Remove assembly from GAC
Write-Host "Removing $assemblyName from GAC" -NoNewline
$returnCode = . $scriptsPath\gacutil.exe /u $assemblyName
if ($LASTEXITCODE -eq 0)
{
Write-Host " - Ok" -ForegroundColor $sectHeadColourALLGo -BackgroundColor $sectBackColourAllGo
}
Else
{
$errors = 1
Write-Host " - Failed" -ForegroundColor Red
$errorString = "$errorString", "Removing $assemblyName from GAC Failed", "$returnCode"
}
}
if ($errors)
{
Write-Host "Failed - review log file at $logFile" -BackgroundColor Red -ForegroundColor White
$errorString | Out-File $logFile
}
}
function UnGacAssembly
{
param([string]$assemblyName)
# Remove assembly from GAC
Write-Host "Removing $assemblyName from GAC" -NoNewline
$returnCode = . $scriptsPath\gacutil.exe /u $assemblyName
}
function GacAssembly
{
param([string]$assemblyName, [string]$assemblyFolder)
# Add assembly to GAC
Write-Host "Adding $assemblyName to GAC" -NoNewline
$returnCode = . $scriptsPath\gacutil.exe /if $assemblyFolder\$assemblyName}
FILE 5
Release.ps1: - create one file like this in the scripts folder of each application directory
loads the functions from functions.ps1 for re-usability
performs the required deployment tasks for each application
Release.ps1
# Deploy BizTalk solution - Myapps.Biztalk.CommonArtifacts
# 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')
)
#Get current location of calling bat file
[string]$path = Get-Location
#Use current location as reference for correct folder structure
$applicationPath = $path + "\Applications"
$logPath = $path + "\Logs"
$scriptsPath = $path + "\Scripts"
# Call BTSFunctions file
Write-Host "Loading functions list"
. .\Scripts\Functions.ps1
# Application specific variables
$biztalkApplication = "Myapps.Biztalk.CommonArtifacts"
#Applications depending on this must be removed first
[string[]]$biztalkapplicationnames = ("Myapps.Biztalk.Application2", "Myapps.Biztalk.Application3")
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - #
Write-Host "`nVariables" -ForegroundColor Gray
Write-Host "Installation Path" $path -Separator `t
Write-Host "Applications Path" $applicationPath -Separator `t
Write-Host "Log Path " $logPath -Separator `t
Write-Host "Scripts Path " $scriptsPath -Separator `t$Error.Clear()
#Create folders... you can create any required file receive location or send port folders too!Write-Host "Creating Inbound Folder... Ignore errors here"
Write-Host "Folder D:\BizTalkFileDrops\CommonArtifacts\Inbound"
if (!(Test-Path -path D:\BizTalkFileDrops\CommonArtifacts\Inbound\))
{
New-Item D:\BizTalkFileDrops\CommonArtifacts\Inbound\ -type directory
if (Test-Path -path D:\BizTalkFileDrops\CommonArtifacts\Inbound\)
{
Write-Host "`nD:\BizTalkFileDrops\CommonArtifacts\Inbound\ folder successfully created" -ForegroundColor $sectHeadColourALLGo -BackgroundColor $sectBackColourAllGo
}
}
# Remove applications dependent on this application
Write-Host "Removing Application dependencies... ignore errors here"
If ($biztalkapplicationnames) {
ForEach ($ap in $biztalkapplicationnames)
{
StopBTSApplication $ap "$logPath\StopApplication_$ap.log"
RemoveBTSApplication $ap "$logPath\RemoveApplication_$ap.log"
}
}
#Remove this application
StopBTSApplication $biztalkApplication "$logPath\StopApplication_$biztalkApplication.log"
# Now Re-Create application
CreateBTSApplication $biztalkApplication "$logPath\CreateApplication_$biztalkApplication.log"
# Import application msi into BizTalk
ImportBTSApplication $biztalkApplication "$applicationPath\$biztalkApplication.msi" "$logPath\ImportApplication_$biztalkApplication.log"
# Import application bindings
ImportBinding "$biztalkApplication" "$bindingsPath\$biztalkApplication.BindingInfo.xml" "$logPath\Importbindings_$biztalkApplication.log"
# Install msi
InstallMSI "$applicationPath\$biztalkApplication.msi" "$logPath\$biztalkApplication.msi.install.log"
# Restart Host Instances
RestartHostInstances $logPath + "\RestartHostinstances.log"
#Start application (if necessary)
StartBTSApplication $biztalkApplication "$logPath\StartApplication_$ap.log"
..............................................................................
this script could be further modified to do a host of useful things like:
replacing the BTs config file (BTSNTSvc64.exe.config) to include app configurations
removing and adding assemblies to gac
adding pipeline components and custom functoids etc
No comments:
Post a Comment