Need a single server BizTalk Environment on Azure IaaS? Just give this a click!

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

BAM Portal: This website uses a data provider that may be unsafe. If you trust the website, click OK, otherwise click Cancel

BAM Portal: This website uses a data provider that may be unsafe. If you trust the website, click OK, otherwise click Cancel

When we try to access BAM Portal, sometimes Office Web Components Display Cross-Domain warning messages such as: “This Web site uses a data provider that may be unsafe. If you trust the Web site, click OK, otherwise click Cancel.” Or this other common warning messages “This page accesses data on another domain. Do you want […]
Blog Post by: Sandro Pereira

Cannot generate serialization assembly {AssemblyName}.XmlSerializers.dll because it already exists. Use /force to force an overwrite of the existing assembly.

Cannot generate serialization assembly {AssemblyName}.XmlSerializers.dll because it already exists. Use /force to force an overwrite of the existing assembly.

For some reason after having migrated a BizTalk 2006/Visual Studio 2005 solution to BizTalk 2010/VS 2010 using Visual Studio Conversion Wizard, I got the following error: "Cannot generate serialization assembly {AssemblyName}.XmlSerializers.dll because it already exists. Use /force to force an overwrite of the existing assembly" The migration of this project was divided into two parts: […]
Blog Post by: Sandro Pereira

Cannot use a prefix with an empty namespace error message when trying to compile a BizTalk Server 2004 solution

Cannot use a prefix with an empty namespace error message when trying to compile a BizTalk Server 2004 solution

I know this is old stuff but sometimes we find customers with solutions running in older versions of BizTalk that need to be fixed or improved while the client studying the possibility of migrating this project to newer versions of BizTalk Server. After the challenge of putting my BizTalk Server 2004 development machine running on […]
Blog Post by: Sandro Pereira

New BizTalk Services Mapper

New BizTalk Services Mapper

Hello Everyone,

 

I’ve been doing the tutorials from the new Windows Azure BizTalk Services, and I wanted to share a few things I’ve discovered with the new mapper.

 

The new transform capability is XAML based by default, not XSLT.  There is however XSLT support by separately creating your XSLT and referencing it from the TRFM by clicking in the empty space of the mapping surface and setting the XSLT property:

image

 

Next, the CSharp Scripting “Map Operation”.  The “Text” field is where you put your custom C# method, and it must be public in scope, or you will get a compilation error:

image

Compilation failed during XAML generation. Error(s) encountered while validating the generated activity :
The private implementation of activity ‘1: DynamicActivity’ has the following validation error:   Compiler error(s) encountered processing expression “genScriptInstance.getLastName(TypeConverter.ToString(ObjectHelper.GetPathValue(srcRoot1, wfPfc23)))”.
‘getLastName’ is not a member of ‘Microsoft.ApplicationServer.Integration.Transforms.GeneratedScriptClass’.

 

 

 

 

 

 

Making the method public results in a successful compile.

image   image

 

Finally, if you are doing the first Tutorial (“Create the Agreement” – Step 4), you will need to extract the sample EDI file from the old April 2012 Release, as I can’t seem to find it anywhere in the SDK samples from the July 2013 release.

image   image

I’m sure there will be more, so if I find more, I’ll post additional information.

 

Cheers,

Dan

How to install and configure BizTalk360 on BizTalk Server 2013 standalone machine running on Windows Server 2012

How to install and configure BizTalk360 on BizTalk Server 2013 standalone machine running on Windows Server 2012

Are you planning to install BizTalk360 on a Windows Server 2012 machine? Check out Installing and Configuring BizTalk360 on Windows Server 2012 / BizTalk Server 2013 (user guide) available for download on BizTalk36o website. This user guide will explain how to install and configure BizTalk360 in an existing Microsoft BizTalk Server 2013 standalone machine (single […]
Blog Post by: Sandro Pereira

Custom Domain Names with BizTalk Services

Background

Each BizTalk Services deployment gets a unique URL like https://contoso.biztalk.windows.net where <contoso> is a globally unique name input by the user. The https session traffic for this deployment will be encrypted using a SSL .pfx certificate. Since the biztalk.windows.net URLs are HTTPS based either a self-signed certificate or a certificate issued by a Certificate Authority is required. Few customers prefer to use their existing domain-friendly URLs like app.contoso.com instead of biztalk.windows.net URLs. The certificate in this case can either be for a generic sub-domain *.contoso.com or for app.contoso.com. All certificates are uploaded to the BizTalk Services deployment during service creation and the Common Name (CN) in the certificate will be validated against the custom domain URL.

Default Domain

The BizTalk Service deployment with the default domain works as follows:

  1. Customer creates BizTalk Services deployment and uploads self-signed certificate for contoso.biztalk.windows.net.
  2. When a application wants to connect with a bridge/agreement endpoint, its first gets the token from ACS
  3. ACS will have the relying party information to return token for contoso.biztalk.windows.net
  4. The application also queries the DNS to determine the IP of the deployment
  5. Azure DNS has a CNAME for contoso.biztalk.windows.net mapping it to contosoXXX.cloudapp.net. The client would get the cloudapp.net URL
  6. Azure DNS also has A record to map the cloudapp.net name to the IP address (VIP) where the service is hosted. The client would get the IP of the deployment
  7. Client application connect to the service at the IP along with the ACS Token
  8. Steps 1-6 are the same if BizTalk Portal queries for data similar to the client application

 

DNS Records

You can use a CNAME record or an A record in DNS to configure custom domains. Both operations require access to the domain’s DNS controller. Any changes to the records requires the changes to be propagated across all servers.

CNAME record

A CNAME is a canonical name aliasing one domain name for another. For example, you can map app.contoso.com to contoso.biztalk.windows.net. Customers can use app.conotos.com for all operations on the corresponding biztalk.net url. Adding this entry is specific to the DNS server (see example later):

app.contoso.com IN CNAME contoso.biztalk.windows.net

It is assumed that contoso.com is already owned by the user.

CNAME with HTTPS

Incase of HTTPS the client/browser will lookup the address and also the certificate of app.contoso.com. The certificate should be available in contoso.biztalk.windows.net since the HTTPS session is established with the latter and the browser requests are being serviced using app.contoso.com URL. For example, if there is a mismatch with the certificate names, the browser would indicate a warning in the address bar.  

A or AAAA record

A record is the address record that maps a DNS domain or a subdomain to its IP Address. While A record is for IP4 addresses, AAAA record is used for IPv6 addresses.

contoso.biztalk.windows.net IN A 1.2.3.4 

Custom Domain with BizTalk Services

There are 3 key steps to getting custom domain working correctly – create the domain name and its SSL certificate, use the certificate and name while deploying BizTalk Services and finally mapping the DNS entries so all calls get routed correctly.

Create Custom Domain and its SSL certificate

  1. You need to register a domain name and create a corresponding SSL certificate as part of the process or using your existing domain name and SSL certificate. If you are purchasing a certificate, it can be for a specific sub-domain like app.contoso.com or generic *.contoso.com
  2. If the SSL certificate is a .pem certificate, you would need to convert it into a .pfx certificate (this is the same as pkcs12 version)

Configure BizTalk Services

  1. Create BizTalk Services deployment with app.contoso.com as custom domain name

   2. Upload the .pfx certificate in the BizTalk Services creation wizard

Configure DNS

  1. Log into to you DNS server to manage your DNS entries.
  2. Add a CNAME record mapping app.contoso.info to contoso.biztalk.windows.net

How this works

The BizTalk Service deployment with custom domain works as follows:

  1. When a client application wants to connect with a bridge/agreement endpoint, its addresses app.contoso.com domain
  2. Client application first gets the token from ACS for app.contoso.com
  3. ACS will have the relying party information to return token for app.contoso.com not contoso.biztalk.windows.net
  4. Client application also queries the Customer DNS, which responds back with contoso.biztalk.windows.net
  5. Client then queries the Azure DNS for contoso.biztalk.windows.net and gets back contosoXXX.cloudapp.net
  6. Client again queries the Azure DNS for contosoXXX.cloudapp.net and determines the IP as 1.2.3.4
  7. Client connects to this IP address and passes the ACS token
  8. Steps 2-7 are the same if BizTalk Portal queries for data similar to client application

 

 

 

Verification

After custom domain has been successfully configured you can check the settings in the following places:

  1. From the Azure portal, check Service URL in the dashboard quick glance information
  2. For EAI, the bridge configuration surface in Visual Studio should be set to the domain URL after installing the relevant client certificate.
  3. The Output window would indicate the custom domain bridge URL during deployment
  4. For EDI, all deployed agreements will have the domain URL as part of the inbound URL in send side and transport of the receive side in X12 and AS2 agreements. 

FAQ

  • Can I use more than one custom domain name per BizTalk Services deployment?

No, currently we support only one domain certificate with a single name for each deployment

  • How do I use certificates with extensions other than .pfx?

You would have to convert certificates with extensions like .pem, .p7b to .pfx. There are tools available to have this conversion as long as the private key of the certificate is available

  • How do update an expired certificate of a domain name?

From the Azure portal, navigate to the dashboard page and you have an option to update the domain certificate of your BizTalk Services deployment

  • Can I change the domain name for a deployment after the BizTalk Service has been created?

In v1, the domain name with its certificate cannot be changed after the BizTalk Services deployment has been created.

References

 

Blog Post by: BizTalk Blog