This script comes after days and days of trial and error.  During the course of building this script I learned a lot about PowerShell Remoting, PowerShell Scheduled Tasks (which run in some other process by the way), PowerShell Background Tasks, Scheduled Tasks and Remote Desktop.

I am pleased to announce a new, true one click end-to-end Single BizTalk Server deployment script. 

Download the Create and Remove Single BizTalk Server PowerShell script. (Right click, Save as)

Why all is issues?  Well, Jeremie wrote it up well and developed his own one-click process.  He went about it a much better way I would say but I needed something that worked with the BizTalk Provisioning Tool in order to get it into a multi-server build out (coming soon).  The core issue is with Configure.exe that shows a message box, thus needs a user to be logged in.  I tried many different ways to spoof a user being logged in without any luck.

First off, I should say I was VERY creative when creating this script.  I am not saying this is the best way to solve the problem nor is it pretty in any way.  It is “hacky” but it gets the job done in about 22 minutes.  I just used the script today to spin up 2 BizTalk groups for a Service Bus Demo so I find it helpful.    I used a few other blog posts and tools in the process.  I tried to reference them in the scripts. 

Here is what the script does:

  1. Create VM and open the HTTP port (easy part)
    1. Creates an Affinity Group
    2. Creates a Storage Account
    3. Creates a Service
    4. Creates a VM
  2. Via Remote PowerShell
    1. Download a bunch of helper files to the VM (you can see them in the script)
    2. Update values in the helper configuration files
    3. Create a Scheduled Task to run when the user logs in
  3. Call remote desktop on the local computer to log in (be careful not to close the window by accident – it logs off when done)
  4. Scheduled task will configure BizTalk using the BizTalk Provisioning Tool
  5. Via Remote PowerShell
    1. Poll for the configuration to be complete
    2. Once done, install BizTalk360 (Bonus!!!  And it’s available on the open HTTP port)
    3. Remove scheduled task
  6. Local clean up on client machine

The script will tell you the time it ran and the URL to access BizTalk 360 after installation.  BizTalk 360 is a great addition to BizTalk running in Windows Azure IaaS because it allows for remote, web based administration.  You do need to get a free 14-day trial key. 

The default user name is demouser and password is “Biztalk01”.  You can use that to access the Virtual Machine using remote desktop or BizTalk 360.

Love to hear any feedback, hopefully a few success stories, and how anyone else has overcome the issues with Configure.exe.

Watch for the multi-server configuration script, giving a full end to end BizTalk domain, in a week or so.

 

Create Single BizTalk Server Raw PowerShell Script

# True One-click end-to-end BizTalk360 setup
# Script by Stephen W. Thomas - BizTalkGuru.com
# Get the latest scripts at www.BizTalkGurus.com
# Version 1.0.0  July 15th, 2013
 
$baseVMName = 'SWT1234'                              # UPDATE - this needs to be globally unique, like initials and 4 random numbers
$subscriptionName = 'ANAME'                          # UPDATE - this is your subscription name 
$dataCenter = 'West US'                              # UPDATE - datecenter to use from Get-AzureLocation
 
$adminUserName = 'demouser'     #Admin user name
$password = 'Biztalk01'     # Admin password
$size = 'Large'     # The size of the VM to create
$imageBTSEval = '2cdc6229df6344129ee553dd3499f0d3__BizTalk-Server-2013-Evaluation'     # BizTalk 2013 Evaluation disk 
 
$setupDir = "C:\BizTalkGurus"     # Local File path
$vmnameBT360 = "$baseVMName-bt"     # This will be the Service and VM name
$affinityGroup = "$baseVMName-ag"     # This is the Affinity Group name
$storageAccount = $baseVMName + "store"     # This is the storage account name
 
#
# --- No changes are needed below this line ---
#
 
# From http://michaelwasham.com/2013/04/16/windows-azure-powershell-updates-for-iaas-ga/
# To Automate Remote Powershell
function InstallWinRMCert($serviceName, $vmname)
{
    $winRMCert = (Get-AzureVM -ServiceName $serviceName -Name $vmname | select -ExpandProperty vm).DefaultWinRMCertificateThumbprint
 
    $AzureX509cert = Get-AzureCertificate -ServiceName $serviceName -Thumbprint $winRMCert -ThumbprintAlgorithm sha1
 
    $certTempFile = [IO.Path]::GetTempFileName()
    Write-Host $certTempFile
    $AzureX509cert.Data | Out-File $certTempFile
 
    # Target The Cert That Needs To Be Imported
    $CertToImport = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2 $certTempFile
 
    $store = New-Object System.Security.Cryptography.X509Certificates.X509Store "Root", "LocalMachine"
    $store.Certificates.Count
    $store.Open([System.Security.Cryptography.X509Certificates.OpenFlags]::ReadWrite)
    $store.Add($CertToImport)
    $store.Close()
 
    Remove-Item $certTempFile
}
 
cls
$startTime = get-date
"Starting at $startTime"
 
Set-AzureSubscription -SubscriptionName $subscriptionName -CurrentStorageAccount $storageAccount
Select-AzureSubscription -SubscriptionName $subscriptionName
 
New-AzureAffinityGroup -Name $affinityGroup -Location $dataCenter -ErrorAction Stop
"Affinity Group Created"
 
New-AzureStorageAccount -StorageAccountName $storageAccount -Label "BizTalk Eval Storage" -AffinityGroup $affinityGroup -ErrorAction Stop
"Storage Account Created"
 
# Make sure all the Services are running
Start-Sleep -s 20
 
# BizTalk Evaluation Configuration
$MyVM1 = New-AzureVMConfig -name $vmnameBT360 -InstanceSize $size -ImageName $imageBTSEval `
    | Add-AzureProvisioningConfig -Windows -AdminUsername $adminUserName -Password $password `
    | Add-AzureEndpoint -Name 'HTTP' -LocalPort 80 -PublicPort 80 -Protocol tcp
 
New-AzureVM -ServiceName $vmnameBT360 -AffinityGroup $affinityGroup -VMs $MyVM1 -WaitForBoot
"Virtual Machine Created"
 
# Give all the servies time to start
Start-Sleep -s 20
 
# Remote PowerShell Details
# Create the Credentials for Remote PowerShell
$strPassword = ConvertTo-SecureString $password -AsPlainText -Force
$credential = New-Object System.Management.Automation.PSCredential ($adminUserName, $strPassword)
 
$uriBT360 = Get-AzureWinRMUri -ServiceName $vmnameBT360 -Name $vmnameBT360 
 
InstallWinRMCert $vmnameBT360 $vmnameBT360
"Installed Certificate"
 
Invoke-Command -ConnectionUri $uriBT360.ToString() -Credential $credential -ScriptBlock {
    param($vmnameBT360, $adminUserName, $password)
    
    Set-ExecutionPolicy Unrestricted
 
    $setupDir = "C:\BizTalkGurus"
    
    if ([System.IO.Directory]::Exists($setupDir)) { Remove-Item $setupDir -Force -Recurse }
        mkdir $setupDir;
    
    # Download Needed Files for BizTalk Multi-Server Configuration
    $remoteUriConfig = "https://biztalkgurus.blob.core.windows.net/tools/multinodeconfigDemo.xml"
    $fileNameConfig = "$setupDir\multinodeconfigDemo_o.xml"
    $webClientConfig = new-object System.Net.WebClient
    $webClientConfig.DownloadFile($remoteUriConfig, $fileNameConfig)   
 
    # Download Needed Files for Running PowerShell
    $remoteUriHelper = "https://biztalkgurus.blob.core.windows.net/tools/StartPowershell.exe"
    $fileNameHelper = "$setupDir\StartPowershell.exe"
    $webClientHelper = new-object System.Net.WebClient
    $webClientHelper.DownloadFile($remoteUriHelper, $fileNameHelper)   
 
    # Download Needed Files for PowerShell
    $remoteUriPowerShell = "https://biztalkgurus.blob.core.windows.net/tools/RunLocalClient.ps1"
    $fileNamePowerShell = "$setupDir\RunLocalClient.ps1"
    $webClientPowerShell = new-object System.Net.WebClient
    $webClientPowerShell.DownloadFile($remoteUriPowerShell, $fileNamePowerShell)
 
    # Download Needed Files for RDHelper
    $remoteUriRDHelper = "https://biztalkgurus.blob.core.windows.net/tools/RunBizTalkTask.xml"
    $fileNameRDHelper = "$setupDir\RunBizTalkTask_o.xml"
    $webClientRDHelper = new-object System.Net.WebClient
    $webClientRDHelper.DownloadFile($remoteUriRDHelper, $fileNameRDHelper) 
 
    # Update wtih computer and user information
    $configFileTask = Get-Content("$setupDir\RunBizTalkTask_o.xml")
    $configFileTask = $configFileTask.Replace("COMPUTERNAME", $vmnameBT360);
    $configFileTask = $configFileTask.Replace("USERACCOUNT", $adminUserName);
    $configFileTask | out-File "$setupDir\RunBizTalkTask.xml" -Encoding ascii
    
    # Update wtih computer and user information
    $configFile = Get-Content("$setupDir\multinodeconfigDemo_o.xml")
    $configFile = $configFile.Replace("COMPUTERNAME", $vmnameBT360);
    $configFile = $configFile.Replace("USERACCOUNT", $adminUserName);
    $configFile = $configFile.Replace("USERPASSWORD", $password);
    $configFile | out-file "C:\BizTalk_Provisioning\multinodeconfigDemo.xml" -Encoding utf8
    
    iex "C:\Windows\System32\schtasks.exe /Create /XML:$setupDir\RunBizTalkTask.xml /TN:ConfigBizTalk"
} -ArgumentList $vmnameBT360, $adminUserName, $password
"Remote PowerShell on Client is complete"
 
# Give the services time to start
Start-Sleep -s 20
 
# End here to just create the BizTalk VM.  Configuration will happen once you log in.  
# Ensure to remove the Scheduled Task once configuration completes.  It takes about 10 minutes.
 
# Get Remote Desktop helper locally
if ([System.IO.Directory]::Exists($setupDir)) { Remove-Item $setupDir -Force -Recurse }
    mkdir $setupDir;
    
# Download Needed Files for Remote Desktop automation
$remoteUriRDP = "https://biztalkgurus.blob.core.windows.net/tools/rdp.exe"
$fileNameRDP = "$setupDir\rdp.exe"
$webClientRDP = new-object System.Net.WebClient
$webClientRDP.DownloadFile($remoteUriRDP, $fileNameRDP)   
 
# Get the port for the RDP End Point
$drpPort = (Get-AzureVM –ServiceName $vmnameBT360 –Name $vmnameBT360 | Get-AzureEndpoint | Where-Object {$_.Name.contains('RDP')}).Port
 
# From http://www.donkz.nl/
iex "$fileNameRDP /v:$vmnameBT360.cloudapp.net:$drpPort /u:$adminUserName /p:$password /h:1 /w:1"
"Local Remote Desktop complete"
 
# Cleanup
Invoke-Command -ConnectionUri $uriBT360.ToString() -Credential $credential -ScriptBlock {
    $setupDir = "C:\BizTalkGurus"
    $doneFile = "$setupDir\done.txt"
    
    while (!(Test-Path -Path $doneFile)) {
        "Waiting for process to complete ..."
        Start-Sleep -s 30
    }
 
    iex "C:\Windows\System32\schtasks.exe /Delete /TN:ConfigBizTalk /F"
 
    # Install BizTalk 360 after Configuration
    $remoteUri = "https://biztalk360.blob.core.windows.net/tools/Kovai.BizTalk360.EasyInstaller.exe"
    $setupDir = "C:\BizTalk360\";C:\BizTalk360\Kovai.BizTalk360.EasyInstaller.exe"/silent true"/hide true"Script run time " + ($endTime - $startTime)You can access BizTalk360 at http://$vmnameBT360.cloudapp.net/BizTalk360/"User name is $adminUserName and the password is $password"
    
    if ([System.IO.Directory]::Exists($setupDir)) { Remove-Item $setupDir -Force -Recurse }
        mkdir $setupDir;
    
    $fileName = "
    $webClient = new-object System.Net.WebClient
    $webClient.DownloadFile($remoteUri, $fileName) 
    
    $Arguments = @()
    $Arguments += "
    $Arguments += "
    start-process C:\BizTalk360\Kovai.BizTalk360.EasyInstaller.exe -wait -windowstyle Hidden -ArgumentList $Arguments
}
 
# Cleanup local
Remove-Item $setupDir -Force -Recurse 
 
$endTime = get-date
"
"
"

Remove Single BizTalk Server PowerShell Script

# True One-click end-to-end BizTalk360 setup
# Full cleanup script - requires PowerShell release 06.03 (from June 3rd, 2013) or better.
# Script by Stephen W. Thomas - BizTalkGuru.com
# Get the latest scripts at www.BizTalkGurus.com
# Version 1.0.0  July 15th, 2013

$baseVMName = 'SWT1234'                 # UPDATE - this needs to be globally unique, like initials and 4 random numbers
$subscriptionName = 'ANAME'             # UPDATE - this is your subscription name 

Set-AzureSubscription -SubscriptionName $subscriptionName
Select-AzureSubscription -SubscriptionName $subscriptionName

$vmnameBT360 = "$baseVMName-bt"
$affinityGroup = "$baseVMName-ag"
$storageAccount = $baseVMName + "store"

Stop-AzureVM -Name $vmnameBT360 -ServiceName $vmnameBT360 -StayProvisioned $false -ErrorAction SilentlyContinue
Remove-AzureVM -Name $vmnameBT360 -ServiceName $vmnameBT360 -ErrorAction SilentlyContinue
Remove-AzureService -ServiceName $vmnameBT360 -Force -ErrorAction SilentlyContinue

$hasDisk = Get-AzureDisk | Where-Object {$_.DiskName.contains("$vmnameBT360")}

# Delete the disks
do {
    "Waiting to try to remove the disk"
    Start-Sleep -s 30
    Get-AzureDisk | Where-Object {$_.DiskName.contains("$vmnameBT360")} | Remove-AzureDisk -DeleteVHD -ErrorAction SilentlyContinue
    $hasDisk = Get-AzureDisk | Where-Object {$_.DiskName.contains("$vmnameBT360")}
} while($hasDisk)

# Give is a few seconds
Start-Sleep -s 15

# Remove the storage account
Remove-AzureStorageAccount -StorageAccountName $storageAccount

# Give is a few seconds
Start-Sleep -s 15

# Remove the Affinity Group
Remove-AzureAffinityGroup -Name $affinityGroup