Monday 22 July 2013

PowerShell Script to Export All BizTalk Applications from Server (using Powershell Provider for BizTalk)

I recently wrote a PowerShell script to export all the applications from a BizTalk server as MSIs and xml files for Bindings.

I have used "Powershell provider for BizTalk" for this. I found this tool quite useful, it really reduces the line of code you have to write.

I thought I will share it, may be someone finds it useful:

The first 5 lines are to load Powershell Provider.You will need to provide the SQL Server Name to connect to.

Set-ExecutionPolicy –ExecutionPolicy RemoteSigned

Write-Host "Loading Powershell"


$InitializeDefaultBTSDrive = $false


Add-PSSnapin BizTalkFactory.Powershell.Extensions


New-PSDrive -Name BizTalk -PSProvider BizTalk -Root BizTalk:\ -Instance SQLServerName -Database BizTalkMgmtDb

Write-Host "Creating MSI"



Now we will get all applications from Biztalk, excluding System ones.
$Applications = @(Get-ChildItem -Path Biztalk:\Applications |  Where-Object {$_.IsSystem -eq $false})

Set-Location –Path BizTalk:\Applications



Loop through applications to export, I have used Resource specification to exclude IIS web directories and bindings, if you want to export everything , just skip the portion which removes nodes from ResSpec xml file :

while($Applications.length -ne 0 -and $Applications -ne $null)

{
Write-Host $Applications.length
Write-Host $Applications[0].Name

$ApplPath = "C:\MSI\" + $Applications[0].Name + ".msi"
$BindPath = "C:\MSI\" + $Applications[0].Name + ".xml"
$ResPath = "C:\MSI\" + $Applications[0].Name + "ResSpec.xml"

Write-Host $ApplPath


(Get-ApplicationResourceSpec -Path $Applications[0].Name).OuterXml | Out-File $ResPath 


$xmlResource = [xml] (Get-Content $ResPath )


$delnodes = $xmlResource.SelectNodes("/*[local-name()='ResourceSpec' and namespace-uri()='http://schemas.microsoft.com/BizTalk/ApplicationDeployment/ResourceSpec/2004/12']/*[local-name()='Resources' and namespace-uri()='http://schemas.microsoft.com/BizTalk/ApplicationDeployment/ResourceSpec/2004/12']/*[local-name()='Resource' and namespace-uri()='http://schemas.microsoft.com/BizTalk/ApplicationDeployment/ResourceSpec/2004/12'][@Type='System.BizTalk:WebDirectory']")


    ForEach($delnode in $delnodes)

    {
        [void]$xmlResource.ResourceSpec.Resources.RemoveChild($delnode)
    }

 $delnodes = $xmlResource.SelectNodes("/*[local-name()='ResourceSpec' and namespace-uri()='http://schemas.microsoft.com/BizTalk/ApplicationDeployment/ResourceSpec/2004/12']/*[local-name()='Resources' and namespace-uri()='http://schemas.microsoft.com/BizTalk/ApplicationDeployment/ResourceSpec/2004/12']/*[local-name()='Resource' and namespace-uri()='http://schemas.microsoft.com/BizTalk/ApplicationDeployment/ResourceSpec/2004/12'][@Type='System.BizTalk:BizTalkBinding'][@Luid='Application/$appName']")


    ForEach($delnode in $delnodes)

    {
        [void]$xmlResource.ResourceSpec.Resources.RemoveChild($delnode)
    }

$xmlResource.Save($ResPath )


Export-Application -Path $Applications[0].Name -Package $ApplPath –ResourceSpec $ResPath


Export-Bindings -Path $Applications[0].Name -Destination $BindPath


if($Applications.length -eq 1)

{
$Applications = $null
}
else
{
$Applications = $Applications[1..($Applications.length -1)]
}
}

Write-Host "MSI and Bindings exported"


When you run the script (using Powershell (x86)) it will export all the applications as MSI and binding files in a file location(C:\MSI).





Wednesday 29 May 2013

Custom File Adapter not releasing file lock

Recently, I got a chance to customize the file adapter to be able to access a remote location, providing UserName and Password.

I started with the File Adapter sample provided with BizTalk. The changes were easy , modifying the ReceiveLocation.xsd schema allowed to me to add properties like Domain, UserName and Password to the adapter properties. And some code changes to access remote location after providing username and password to receive files.

Deploying the new changes I faced one issue, my new adapter properties were not visible on BizTalk Admin Console.
I had correctly deployed my dlls to GAC, my registry settings were correct, pointing to correct dlls. So changes should have been there. After some investigation, I found that we need to close and reopen BizTalk Admin Console in order for the changes to appear. Ha... so
-> Add the adapter under Platform settings. Restart Host Instance.
-> Close Admin Console and then reopen, you will have your new changes.

So, now I could access the files on remote location after providing correct username and password. However, I was facing a strange issue.
My files were being renamed to .BTS_WIP and were not being deleted. In event log I had errors saying, "Cannot delete file because it is being used by another process".
Now, what was using my file. I could not manually delete files as well. Only after I stopped Host Instance, I was able to delete the file.

After debugging the code, it turned out that there is some cleanup code which calls GC.Collect() to release resources in the sample. Before the GC.Collect() is completed, File.Delete() was being called in a separate thread ofcourse.
So , I thought of placing my File.Delete() with in a try catch block and in the catch block, I called :
System.GC.Collect();
System.GC.WaitForPendingFinalizers();
File.Delete()

It did the trick!!!