This project has moved and is read-only. For the latest updates, please go here.

Batching the installs

Topics: Server Deployment
May 21, 2010 at 12:47 AM

This might be a feature request related to handling many projects.  But maybe there is an existing feature I could use.

When we install the MSI, and click the checkbox, then install with the WIX screens begins.  Is thee anyway to enter the data that we normally enter on the WIX screens on a command line?  Maybe that feature is already built in to the WIX installers, or maybe that needs to be part of my previous enhancement request.   If possible, then we could move to a 100% batch install, where at  least it would continue from application to the next as long as there were 0 errors. 




May 21, 2010 at 9:11 PM

Yes, you can completely automate the install.  You can install the MSI with msiexec.exe from a script.  Then run EnvironmentSettingsExporter.exe to export the settings XML files from the settings spreadsheet, then set the environment variable BT_DEPLOY_MGMT_DB to true or false (the "Is this the last server in the group" question) and the ENV_SETTINGS environment variable to the full path to the settings XML file (the "Specify a file containing environment-specific settings" question).  Rather than set those as environment variables, you can also pass them directly as properties to MSBuild.

At that point you can run MSBuild.exe /p:DeployBizTalkMgmtDB=%BT_DEPLOY_MGMT_DB%;Configuration=Server;SkipUndeploy=true /l:FileLogger,Microsoft.Build.Engine;logfile=..\DeployResults\DeployResults.txt <btdfproj path>

The logging part is optional.

This is all the stuff that is happening in the ServerDeploy.bat and ServerDeployWizard.bat which are behind the Start/Deploy menu.  The WiX portion is the MSI installer.  The wizard that comes up after the installer is from SetEnvUI.exe and is driven by InstallWizard.xml and UnInstallWizard.xml.  All it does is collect those configuration values and set them into environment variables.


Jun 21, 2010 at 6:25 PM
Tom, I'm just curious on "Is this the last server in the group" variable BT_DEPLOY_MGMT_DB, may I know how does this setting affect the deployment? Is ENV_SETTINGS refers to local_settings.xml generated by the Excel spreadsheet? Thanks
Jun 21, 2010 at 6:48 PM

Primarily if BT_DEPLOY_MGMT_DB = "false" then the DLL's will be installed in the GAC and not much else.  That's what happens on all but one of the BizTalk servers in a group.  Correct on ENV_SETTINGS, it contains the path to whichever environment-specific settings XML file you wish to use.


Jun 22, 2010 at 5:33 AM

I did the batch file to deploy, but if fails with the error below:

Project "C:\Program Files\Test System\1.0\Deployment\System.Depl
oyment.btdfproj" on node 0 (default targets).
C:\Program Files\Test System\1.0\Deployment\
dfproj : error MSB4057: The target "DeployBizTalkMgmtDB_" does not exist in the
Done Building Project "C:\Program Files\Test System\1.0\Deployme
nt\System.Deployment.btdfproj" (default targets) -- FAILED.


Jun 22, 2010 at 5:43 AM

Looks like you are not setting the value of BT_DEPLOY_MGMT_DB to "true" or "false" through an environment variable or on the MSBuild command-line.

Jun 22, 2010 at 7:33 AM


Thanks for the fix on BT_DEPLOY_MGMT_DB = true.

I still got an error after running the code below after I manually set the ENV_SETTINGS: = C:\program files\Test System\1.0\Deployment\EnvironmentSettings\local_settings.xml

@echo on
@REM For loop is just to keep this generic.
@for %%i in (*.deploy.include) DO Framework\DeployTools\XmlPreprocess.exe /o:%%i /i:%%i /s:"C:\program files\Test System\1.0\Deployment\EnvironmentSettings\local_settings.xml"
"C:\WINDOWS\Microsoft.NET\Framework\v3.5\MSBuild.exe" /p:DeployBizTalkMgmtDB=true;Configuration=Server;SkipUndeploy=true /l:FileLogger,Microsoft.Build.Engine;logfile=..\DeployResult
s\DeployResults.txt System.Deployment.btdfproj



Seems like now the /s: is not working, see the error :

  /s:: Argument expects a parameter

  Usage: XmlPreprocess.exe [@argfile] [/input|i:<value>] [/output|o:<value>]
         [/settings|s:<value>] [/define|d:<value>] [/clean|c] [/quiet|q] [/vali
         [/validateSettingsExist|vs] [/validateXmlWellFormed|vx] [/fixFalse|f]
         [/environment|e:<value>] [/spreadsheet|x:<value>] [/list|l]
         [/property|p:<value>] [/delimiters|t:<value>] [/environmentRow|er:<val


C:\program files\Test System\1.0\Deployment\Framework\BizTalkDep
loymentFramework.targets(1025,5): error MSB3073: The command ""C:\program files
\Test System\1.0\Deployment\Framework\DeployTools\xmlpreprocess.
exe" /f /v /c /i:"C:\program files\Test System\1.0\Deployment\Po
rtBindingsMaster.xml" /o:"C:\program files\Test System\1.0\Deplo
yment\PortBindings.xml" /d:CurDir="C:\program files\Test System\
1.0" /s:""" exited with code 1.
Done Building Project "C:\program files\TestSystem\1.0\Deployme
nt\System.Deployment.btdfproj" (default targets) -- FAILED.

    0 Warning(s)
    1 Error(s)


Jun 22, 2010 at 3:47 PM

I'll be eliminating that line from the batch file in the next release.  If you have additional files that you wish to have XmlPreprocess'ed, place them in your .btdfproj in an ItemGroup with FilesToXmlPreprocess elements.


Aug 2, 2010 at 11:05 PM
Edited Aug 2, 2010 at 11:06 PM
tfabraham wrote:

Looks like you are not setting the value of BT_DEPLOY_MGMT_DB to "true" or "false" through an environment variable or on the MSBuild command-line.

I am attempting this today as well.

I was getting the same error when I did this:


and the fix was to do this:


   [i.e. I removed the spaces around the equal sign]

It's been a while since I've coded .bat/command files. By turning "echo on", I could see that the "true" wasn't getting substituted in the right place. 



Aug 3, 2010 at 1:15 AM
Edited Aug 3, 2010 at 1:16 AM

How does "DeployTools" get passed or set in BizTalkDeploymentFramework.targets?

I'm running a .cmd file with this:

IF EXIST "%windir%\Microsoft.NET\Framework\v3.5\MSBuild.exe" (
SET BTDFMSBuildPath="%windir%\Microsoft.NET\Framework\v3.5\MSBuild.exe"
) ELSE IF EXIST "%windir%\Microsoft.NET\Framework\v2.0.50727\MSBuild.exe" (
SET BTDFMSBuildPath="%windir%\Microsoft.NET\Framework\v2.0.50727\MSBuild.exe"
@echo on

REM - Do This Just One Time - Shred the XML File into 4 Settings Files
"c:\Program Files\FRB.EC.Common\1.0\Deployment\Framework\DeployTools\EnvironmentSettingsExporter.exe" EnvironmentSettings\SettingsFileGenerator.xml EnvironmentSettings

SET ENV_SETTINGS=SharedDev_settings.xml

%BTDFMSBuildPath% "c:\Program Files\MyApp\1.0\Deployment\Framework\BizTalkDeploymentFramework.targets" /p:DeployBizTalkMgmtDB=%BT_DEPLOY_MGMT_DB%;Configuration=Server;SkipUndeploy=true /l:FileLogger,Microsoft.Build.Engine;logfile="c:\Program Files\MyApp\1.0\DeployResults\DeployResults.txt" %1
rem %BTDFMSBuildPath% "c:\Program Files\MyApp\1.0\Deployment\Framework\BizTalkDeploymentFramework.targets" /p:DeployBizTalkMgmtDB=true;Configuration=Server;SkipUndeploy=true /l:FileLogger,Microsoft.Build.Engine;logfile="c:\Program Files\MyApp\1.0\DeployResults\DeployResults.txt" %1

(The echo's show that %1 is not being set to anything.)

The command file is written in such a way so that it sits in a "neutral" directory, and will then run deploys on my 7 different BT projects.

In the error below, I can see the problem is that the directory name "\Framework" is repeating twice, but I can't figure out why. 

  Clearing file attributes for 'PortBindings.xml'.
  The system cannot find the path specified.
c:\Program Files\MyApp\1.0\Deployment\Framework\BizTalkDeployment
Framework.targets(1025,5): error MSB3073: The command ""c:\Program Files\MyApp\
 /f /v /c /i:"c:\Program Files\MyApp\1.0\Deployment\Framework\Por
tBindings.xml" /o:"c:\Program Files\MyApp\1.0\Deployment\Framewor
k\PortBindings.xml" /d:CurDir="c:\Program Files\MyApp\1.0\Deploym
ent" /s:"SharedDev_settings.xml"" exited with code 3.
Done Building Project "c:\Program Files\MyApp\1.0\Deployment\Fram
ework\BizTalkDeploymentFramework.targets" (default targets) -- FAILED.

I can see line 1025-1026


but I cannot figure out where $(DeployTools) is coming from.

Neal Walters





Aug 3, 2010 at 6:04 AM
Edited Aug 4, 2010 at 4:39 PM

The DeployTools property is equal to $(DeploymentFrameworkDir)\DeployTools.
DeploymentFrameworkDir is equal to $(DeploymentFrameworkRootDir)Framework.
On a Server deployment, DeploymentFrameworkRootDir is equal to $(MSBuildProjectDirectory)\. That's where the .btdfproj is located.

Putting those together, on a Server deployment, DeployTools equals $(MSBuildProjectDirectory)\Framework\DeployTools.

Your line above, "%BTDFMSBuildPath% "c:\Program Files\MyApp\1.0\Deployment\Framework\BizTalkDeploymentFramework.targets" <etc.>" should be referencing your .BTDFPROJ file, not BizTalkDeploymentFramework.targets.


Aug 4, 2010 at 4:19 PM

I'm just reporting back what we did.  In the last two days, we created and tested eight command files
[where  (ABC) is an example of our system name]:

1) TerminateABCApps
2) InstallABCApps
3) UninstallABCApps
4) DeployABCApps
5) DeployABCAppsGACOnly (for all but the last machine)
6) UndeployABCApps
7) StartABCApps
8) StopABCApps

The Start/Stop/Terminate use a small MSBuild file that was modeled after your samples. Install/Uninstall run "msiexec" with the /i or /x (and /q - quiet) options.
With these scripts, the full process (terminate, undeploy, uninstall, install, deploy, start) took 22 minutes (out of which the removal process was 8 minutes, and the install/deploy was 16 minutes).
(In this particular app, we have no VDirs, BAM,or Business Rules.)

So at this point, we are near nirvana.

Thanks again for your tool and help!


Aug 4, 2010 at 4:43 PM

You're welcome, I love to hear success stories from using the tool.  That sounds like an awesome solution, total automation.  Do you think there's anything reusable in there that I could package in?


Aug 6, 2010 at 10:52 PM

It's mostly just a combination of what is discussed above, along with the though process of what group "jobs" or "functions" are needed. 
However, if other people have the same need, I think it could easily save them a day or two of time to have working example to start from.

I want to still add error checking.   If I run MSBuild with the .btdfproj file, and there are errors, will it set an error I can check in a command file?  I'm assuming it would, just haven't tested yet.  Right now, one issue would be that if app 2 has an error, it would just keep running.  Then possibly app 5 might depend on app 2, and also error.  I realize the errors are in the deploy/text files, but might also be confusing to the guy deploying it whether or not there were errors if we just keep on going after an error.

I also have now three command files on my dev system:

1) DevEnvBuild - Does Visual Studio "devenv.exe" build on each of the apps
2) DevBTDFBuidlMSI - Builds the BTDF MSI for each of the apps
3) DevGatherMSIs - just takes a target directory as a parm, and copies the MSIs from the 7 various directories to one common directory (typically copied to the target machine for the actual deploy).



Aug 7, 2010 at 12:46 AM

I think it would be great to include a sample of what you've put together.  MSBuild does set the error level, so you could check it in your batch file.


Aug 10, 2010 at 3:54 AM

Hi guys,

First of all I want to say thanks for sharing this wonderful and very useful tool, I am also using this in my project and I'm very happy with the results.

I just want to check about the discussion above on how to automate the installation of MSI into particular environment using the EnvironmentSettingsExporter.exe in a batch file, It will be very helpful and will save me a lot of time to atleast a simple sample of doing this.

Thank you very much

Aug 10, 2010 at 7:07 PM
Edited Aug 10, 2010 at 7:12 PM

Aggalentes: Is that what you want to see?

InstallAll3.cmd - This just installs the MSI without the deploy.

msiexec /i App1.msi /q
msiexec /i App2.msi /q
msiexec /i App3.msi /q


DeployAll3.cmd - This does the deploy of each app 

NOTE: in our case all apps were sharing the same SettingsFileGenerator.xml file.
To run this one you type "DeployAll3 SharedDev"  where for example QA is the name of your environment.
I have listed our current environments in the "missing parm" error message at the bottom. 

IF (%1) ==() GOTO NOPARM

IF EXIST "%windir%\Microsoft.NET\Framework\v3.5\MSBuild.exe" (
SET BTDFMSBuildPath="%windir%\Microsoft.NET\Framework\v3.5\MSBuild.exe"
) ELSE IF EXIST "%windir%\Microsoft.NET\Framework\v2.0.50727\MSBuild.exe" (
SET BTDFMSBuildPath="%windir%\Microsoft.NET\Framework\v2.0.50727\MSBuild.exe"
@echo on

SET ENV_SETTINGS=c:\Program Files\App1\1.0\Deployment\EnvironmentSettings\%1_settings.xml
SET PARMS=DeployBizTalkMgmtDB=%BT_DEPLOY_MGMT_DB%;Configuration=Server;SkipUndeploy=%SKIPUNDEPLOY%

@REM - Do the following for each one of the 7 applications
@REM - Step 2- About DONE With XMLPreprocess, check value DIR1=%DIR1%
@REM "%DIR2%\XmlPreprocess.exe" /o:"%DIR1%/PortBindings.xml" /i:"%DIR1%/PortBindingsMaster.xml" /s:EnvironmentSettings/%ENV_SETTINGS%

ECHO Step 3- DONE With XMLPreprocess
%BTDFMSBuildPath% "c:\Program Files\App1\1.0\Deployment\Company.App.App1.BizTalk.Deployment.btdfproj"  /p:%PARMS% /l:FileLogger,Microsoft.Build.Engine;logfile="c:\Program Files\App1\1.0\DeployResults\DeployResults.txt"
%BTDFMSBuildPath% "c:\Program Files\App2\1.0\Deployment\Company.App.App2.BizTalk.Deployment.btdfproj"  /p:%PARMS% /l:FileLogger,Microsoft.Build.Engine;logfile="c:\Program Files\App2\DeployResults\DeployResults.txt"
%BTDFMSBuildPath% "c:\Program Files\App3\1.0\Deployment\Company.App.App3.BizTalk.Deployment.btdfproj"  /p:%PARMS% /l:FileLogger,Microsoft.Build.Engine;logfile="c:\Program Files\App3\1.0\DeployResults\DeployResults.txt"

@echo on
@echo ----- COMPLETED -----
@echo off
REM This is used to copy ResultsText to a date/time-stamped copy of the file, would need to do this for all 7 apps
REM %BTDFMSBuildPath% Framework\CopyDeployResults.msbuild /nologo

@ECHO ----------------
@ECHO ----------------
@ECHO You must pass one parm that is one of the following values: SharedDev, DFStage, or PROD

The issue still with the above, is that if App3 is dependent on App2, and App2 has an error, then App3 probably should not install. 
In the future, I will try to add "if" statements to check error codes.


Tom, I can scrub and zip the entire dozen files and send you the entire set if you want.






Aug 23, 2010 at 4:56 AM

No, the server deploy MSI does not explicitly create any registry keys, although one of the Windows Installer keys might contain the path if you could locate the right key.

However, the install path IS saved in SSO as ProjectPath when IncludeSSO = true.  You can pull that at runtime inside your app using the SSOSettingsFileReader assembly.


Jan 31, 2012 at 12:53 PM

Since it's in batch file, I've converted it to use Powershell:


	Automates BizTalk Application deployment using BTDF 5.0

	Automates BizTalk Application deployment using BTDF 5.0
			1. It installs the MSI on the specified application path
			2. Calls EnvironmentSettingsExporter to generate the settings xml
			3. Updates Environment Variables
			4. Executes the MSBuild with parameters

	File Name: Install-BizTalkApplication.ps1
	Author: Randy Aldrich Paulo
	Prerequisite: Powershell 2.0, BizTalk Deployment Framework 5.0, BizTalk Server 2010

	MSI File generated using BizTalk Deployment Framework 5.0

.PARAMETER ApplicationInstallPath
	Location wherein the resource files will be copied, it will be use by the BTDF during the deployment

.PARAMETER Environment
	Name of environment (Local,Dev,Test,Prod) to be used, this value will be passed to 
	EnvironmentSettingsExporter and willbe used to construct the environment variable: ENV_SETTINGS

	Install-BizTalkApplication -MsiFile "E:\Installer\Application 1\Application1.msi" 
	-ApplicationInstallPath "E:\Program Files\Application 1"
	-Environment DEV

	Install-BizTalkApplication -msi "E:\Installer\Application 1\Application1.msi" 
	-path "E:\Program Files\Application 1"
	-env TEST

	Install-BizTalkApplication "E:\Installer\Application 1\Application1.msi" 
	"E:\Program Files\Application 1" TEST

	Install-BizTalkApplication "E:\Installer\Application 1\Application1.msi" 
	"E:\Program Files\Application 1" TEST -SkipUndeploy $false

function Install-BizTalkApplication
		[Parameter(Position=0,Mandatory=$true,HelpMessage="Msi file should be existing")]
		[ValidateScript({Test-Path $_})]
		[Parameter(Position=1,HelpMessage="Path wherein the resource file will be installed")]
		[Parameter(Position=2,Mandatory=$true,HelpMessage="Only valid parameters are Local,Dev,Test and Prod")]



	#Step 1 : Run MSI	
		$script = 
		    $args = "-i $MsiFile INSTALLDIR=`"$ApplicationInstallPath`" /qn /norestart"
			Write-Host " Installing MSI File.." -ForegroundColor Cyan
			Write-Host " 	MSI File: $MsiFile" -ForegroundColor DarkGray 
			Write-Host " 	    Args: $args" -ForegroundColor DarkGray 
			$exitCode = (Start-Process -FilePath "msiexec.exe" -ArgumentList $args -Wait -Passthru).ExitCode
			Write-Host "	Exit Code: $exitCode" 
			if($exitCode -ne 0)
				Write-Error "Installing $MsiFile failed!, Exit Code: $exitCode" 
			Write-Host " Installed MSI success.." -ForegroundColor Green
			Write-Host ""
		Invoke-Command -scriptblock $script
	#Step 2 : Run MSBuild & Deploy
			<# Start Step 2.2 Run EnvironmentSettingsExporter, this one generates the xml file 
			(Exported_DevSettings.xml, Exported_LocalSettings.xml etc..)
			$args = "`"" + (Join-Path $ApplicationInstallPath "Deployment\EnvironmentSettings\SettingsFileGenerator.xml") + "`"" + " Deployment\EnvironmentSettings"
			$exePath = ("`"" + (Join-Path $ApplicationInstallPath "\Deployment\Framework\DeployTools\EnvironmentSettingsExporter.exe") + "`"")
			Write-Host " Generating Environment Settings File.."  -ForegroundColor Cyan
			Write-Host "	Location: $exePath" -ForegroundColor DarkGray
			Write-Host " 	Args: $args" -ForegroundColor DarkGray

			$exitCode = (Start-Process -FilePath $exePath -ArgumentList $args -Wait -PassThru).ExitCode
			Write-Host "	Exit Code: $exitCode"
			if($exitCode -ne 0)
				Write-Error " Generating Environment Settings File failed!, Exit Code: $exitCode"
			Write-Host " Generated Environment Settings File. " -ForegroundColor Green
			Write-Host ""
			<# End Step 2.2 Run EnvironmentSettingsExporter, this one generates the xml file 
			(Exported_DevSettings.xml, Exported_LocalSettings.xml etc..)#>

			<# Start Step 2.3 Set the Environment Variables ENV_SETTINGS and BT_DEPLOY_MGMT_DB #>
			$settingsFile = "Deployment\EnvironmentSettings\Exported_{0}Settings.xml" -f $Environment
			$EnvSettings =Join-Path $ApplicationInstallPath $settingsFile

			Write-Host " Setting Environment Variables"  -ForegroundColor Cyan
			Write-Host "	     ENV_SETTINGS = $EnvSettings" -ForegroundColor DarkGray; 
			Set-Item Env:\ENV_SETTINGS -Value $EnvSettings
			Write-Host  "	BT_DEPLOY_MGMT_DB = $BTDeployMgmtDB"  -ForegroundColor DarkGray; 
			Set-Item Env:\BT_DEPLOY_MGMT_DB -Value $BTDeployMgmtDB
			Write-Host " Setted Environment Variables"  -ForegroundColor Green
			Write-Host ""
			<# End Step 2.3 Set the Environment Variables ENV_SETTINGS and BT_DEPLOY_MGMT_DB #>
			<# Start Step 2.4 Execute MS Build with parameters #>
			#Get .NET Version
			$dotNetVersion = gci 'HKLM:\SOFTWARE\Microsoft\NET Framework Setup\NDP' | sort pschildname -des | select -fi 1 -exp pschildname
			if($dotNetVersion = "v4.0") { $dotNetVersion = "v4.0.30319" } #Include other info if .NET 4.0
			if (Test-Path ( Join-Path $env:windir "Microsoft.NET\Framework\$dotNetVersion\MSBuild.exe" ))
				$BTDFMSBuildPath = Join-Path $env:windir "Microsoft.NET\Framework\$dotNetVersion\MSBuild.exe" 
				Write-Host " Using MSBuild $dotNetVersion" -ForegroundColor DarkGray 
				Write-Error " MSBuild not found."
			#Assign MS Build Params
			$logger="FileLogger,Microsoft.Build.Engine;logfile=`"" + ( Join-Path $ApplicationInstallPath "DeployResults\DeployResults.txt" ) + "`""
			$btdfFile="`"" +  (Join-Path $ApplicationInstallPath "Deployment\Deployment.btdfproj") + "`""
			$args = "/p:{1} /l:{2} {0}" -f $btdfFile,$parms,$logger
			Write-Host " Executing MSBuild from: $BTDFMSBuildPath"  -ForegroundColor Cyan 
			Write-Host "	ArgList: $args" -ForegroundColor DarkGray
			#Check MSBuild Return Code
			$exitCode = (Start-Process -FilePath $BTDFMSBuildPath -ArgumentList $args -Wait -Passthru).ExitCode
			Write-Host "	Exit Code: $exitCode" 
			Write-Host ""
			if($exitCode -ne 0)
				Write-Error " Error while calling MSBuild, Exit Code: $exitCode"
			#Copy Log File
			Write-Host "	Copying  Log file."
			$args =  "Deployment\Framework\CopyDeployResults.msbuild /nologo"
			Start-Process -FilePath $BTDFMSBuildPath -ArgumentList $args
			<# End Step 2.4 Execute MS Build with parameters #>
		Write-Host " Running MS Build and deploying.." -ForegroundColor Cyan
		Invoke-Command -scriptblock $script
		Write-Host " Deployed application" -ForegroundColor Green



May 21, 2013 at 11:10 AM
When the msi gets created, a linked bat file is also created.
Is it possible to append this bat file so that when a new version of the msi gets created, the batfile is also correclty filled out.

This way the full deployment of the biztalk project could be automated (including creating Environment Variables and creation of directories etc.)
May 22, 2013 at 7:27 AM
The MSI build just uses the WriteLinesToFile MSBuild task to write the bat file using File="@(InstallBatFile)". You could certainly use that or any other MSBuild task to modify or overwrite the bat file with your own.

If you're on BizTalk 2010 or newer, you can add <Target Name="UpdateBatFile" AfterTargets="Installer"></Target> to the bottom end of your .btdfproj and add the necessary task(s) inside it.