PowerShell Provider 1.0 Beta (hotfix)

25 February 2010

A couple of people have reported a nasty bug in the PowerShell Provider version 1.0 Beta. The provider doesn’t seem to work when SQL Server (hosting the BizTalk management database) is on a remote SQL Server.

Although we will have this fixed in the 1.0 final release I decided to provide a hotfix right now for those who want to play with the beta and have a remote SQL server. This is major show stopper.

If you want to receive the hotfix please drop me an e-mail (see about page of my blog) and I will send you the fix and instructions a.s.a.p.

As an alternative you can download the latest sources from codeplex and compile them yourself.

The hotfix will also fix other reported issues:

- #3042
- #3170
- #3280
- #3390
- #3391
- #3393


Retrieve the BTSNTSvc.exe PID with PowerShell

5 January 2010

Again another post in the series of more advanced things you can do with the PowerShell provider for BizTalk.

When debugging BizTalk solutions you find yourself many times in a situation where you need to attach the Visual Studio debugger to the running BizTalk host instance. This is very easy to do. In Visual Studio you simply select ‘Debug’ then ‘Attach to Process’. From the dialog you select the ‘BTSNTSvc.exe’ process and finally click the ‘Attach’ button.

image

It gets a little more tricky when you have multiple host instances running on your development box. The dialog now shows all host instances and you need to pick the one running the artifact (pipeline component, orchestration, etc.) that you want to debug. The bad thing is that there is no readable name displayed and the only property that distinguishes between the instances is the PID (column: ID). So how do you know how to pick the correct one and go on debugging?

There are basically two approaches:

- You select all the ‘BTSNTSvc.exe’ process in order to attach the debugger to all of them.

- You use some tooling to find out the PID.

Although the first option works, it is not the best solution. Attaching to all processes takes more time and resources so it is better to just pick the right one.

Now this is nothing new and there have been a number of smart people that blogged about methods to find out the PID for a host instance. Samples are here and here.

In this post I want to show the PowerShell way of doing this.

When I use the ‘Get-ChildItems’ cmdlet on the host instances container PowerShell shows a list of ‘BTSHostInstance’ objects in the console:

image

Since the process id is not a property of the ‘BTSHostInstance’ object it is not shown in the list.

Fortunately the nice thing about PowerShell is that you can extend properties with extra members using the Add-Member cmdlet. In the script below I create a function that adds a a property containing the process id to every non isolated host.

function GetHostPID
{
    Get-ChildItem -Path 'Biztalk:\Platform Settings\Host Instances' | ForEach-Object {

        if ($_.HostType -ne 'Isolated')
        {
            [string]$a = (Get-WmiObject Win32_Process -filter "CommandLine Like '%$($_.HostName)%'").ProcessId
       
            $_ | Add-Member -MemberType NoteProperty -Name PID -Value $a
       
            Write-Output $_
              
        }
    } | Format-Table PID, Name, HostName, NTGroupName, RunningServer, HostType, ServiceState
}

When I execute the function I get a nice list similar to the list above but with the PID added to every row:

image

I can add this function to my function library so it loads automatically on startup and is always available in my PowerShell console.

Of course you can do this without the PowerShell provider for BizTalk and use WMI only. In that case it would be hard and require far more lines of code to get a nice formatted list like show above.


Awarded MVP BizTalk Server 2010

5 January 2010

I had a great start of this new year. On January, 1st I received the ‘Congratulations 2010 Microsoft MVP!’ email from Microsoft. I almost missed it because it was delivered to the junk mail folder. I do not check that folder too often :-)

I’m really honored and excited. I would like to thank the people at Microsoft, community members and other people involved. Special thanks to fellow MVP Jan Eliasen (IMHO: the book will be great :-) ) and codeplex powershell team members: Maxime and Michel.

No MVP logo? Well, I’m waiting for access to the MVP logo kit :-)


Empowering BizTalk in HotRod Magazine

24 December 2009

Yesterday the new issue of BizTalk HotRod Magazine was published. Besides other nice content it contains an article on our PowerShell Provider for BizTalk.


Copying your host configuration

22 December 2009

Moving your host configuration from one server to another can be daunting and time consuming task. This usually needs to be done when you hand over stuff from development to test, or from test to production. On those environments you mostly want to have the exact same host configuration as you have on your development box.

Another option is that a new development team member has just started on a fresh development box and you want him to use the same host configuration that you have. There are a lot of other scenarios where you want to copy the configuration of your hosts and host instances to another machine.

A lot of great BizTalk people have already showed how this can be done in an automated way. Some samples are:

- VBScript and WMI
- Custom tool 1
- Custom tool 2

In this post I want to show you how this can be done using PowerShell and the PowerShell provider for BizTalk. So this is actually the next post in my series on more advanced things you can do with the provider.

I use a slightly different approach compared to the existing tools. I use a PowerShell script that can be executed on the source server. This is the server that already has the host configuration set up, for example a development server. The output of running this script is actually another PowerShell script that you can run on the destination server. This output scripts contains all necessary statements to create the hosts, corresponding host instances and settings.

This is how it works:

- execute the script
- the script prompts for the name and path of the output file:

image

- after a short while the script is finished and a PowerShell script is created. You can run this script on the destination server or send it to an administrator who will run it on another server.

This is the created script:


#Determine BizTalk root and switch to host container.
$BizTalkRoot = (get-psdrive -PsProvider BizTalk).Root
Join-Path $BizTalkRoot 'Platform Settings\Hosts' | Set-Location

$RunningServer = $Env:ComputerName
#Create hosts
#Create host 'ReceiveHost' and set properties.
New-Item -Path 'ReceiveHost' -HostType 'InProcess' -NtGroupName 'BizTalk Application Users' -AuthTrusted:$False
Set-ItemProperty -Path 'ReceiveHost' -Name HostTracking -Value False
Set-ItemProperty -Path 'ReceiveHost' -Name Is32BitOnly -Value True

#Create host 'ProcessingHost' and set properties.
New-Item -Path 'ProcessingHost' -HostType 'InProcess' -NtGroupName 'BizTalk Application Users' -AuthTrusted:$False
Set-ItemProperty -Path 'ProcessingHost' -Name HostTracking -Value False
Set-ItemProperty -Path 'ProcessingHost' -Name Is32BitOnly -Value True

#Create host 'SendHost' and set properties.
New-Item -Path 'SendHost' -HostType 'InProcess' -NtGroupName 'BizTalk Application Users' -AuthTrusted:$False
Set-ItemProperty -Path 'SendHost' -Name HostTracking -Value False
Set-ItemProperty -Path 'SendHost' -Name Is32BitOnly -Value False

#Create host 'TrackingHost' and set properties.
New-Item -Path 'TrackingHost' -HostType 'InProcess' -NtGroupName 'BizTalk Application Users' -AuthTrusted:$False
Set-ItemProperty -Path 'TrackingHost' -Name HostTracking -Value True
Set-ItemProperty -Path 'TrackingHost' -Name Is32BitOnly -Value False

#Switch to host instances container.
Join-Path $BizTalkRoot 'Platform Settings\Host Instances' | Set-Location

#Create host instances
#Create host instance 'Microsoft BizTalk Server ReceiveHost BTS2K9-DEV' and set properties.
$Credential = $Host.UI.PromptForCredential('Host Instance user credentials', 'Please enter credentials for host instance ''ReceiveHost''', '', '')
New-Item -Path 'hostinstance' -HostName 'ReceiveHost' -RunningServer $RunningServer -Credentials $Credential
Set-ItemProperty -Path 'Microsoft BizTalk Server ReceiveHost BTS2K9-DEV' -Name IsDisabled -Value False

#Create host instance 'Microsoft BizTalk Server ProcessingHost BTS2K9-DEV' and set properties.
$Credential = $Host.UI.PromptForCredential('Host Instance user credentials', 'Please enter credentials for host instance ''ProcessingHost''', '', '')
New-Item -Path 'hostinstance' -HostName 'ProcessingHost' -RunningServer $RunningServer -Credentials $Credential
Set-ItemProperty -Path 'Microsoft BizTalk Server ProcessingHost BTS2K9-DEV' -Name IsDisabled -Value False

#Create host instance 'Microsoft BizTalk Server SendHost BTS2K9-DEV' and set properties.
$Credential = $Host.UI.PromptForCredential('Host Instance user credentials', 'Please enter credentials for host instance ''SendHost''', '', '')
New-Item -Path 'hostinstance' -HostName 'SendHost' -RunningServer $RunningServer -Credentials $Credential
Set-ItemProperty -Path 'Microsoft BizTalk Server SendHost BTS2K9-DEV' -Name IsDisabled -Value False

#Create host instance 'Microsoft BizTalk Server TrackingHost BTS2K9-DEV' and set properties.
$Credential = $Host.UI.PromptForCredential('Host Instance user credentials', 'Please enter credentials for host instance ''TrackingHost''', '', '')
New-Item -Path 'hostinstance' -HostName 'TrackingHost' -RunningServer $RunningServer -Credentials $Credential
Set-ItemProperty -Path 'Microsoft BizTalk Server TrackingHost BTS2K9-DEV' -Name IsDisabled -Value False

There are a couple of things to mention about the generated script:

- This is by no means a script applicable for all situations and environments. The purpose is just to show the output script as a result of running the source script. The source script will probably need some modification to make it apply to your environment. For example the script does not take into account multi server configurations, etc.
- The output script will prompt for credentials for each host instance it will create. There are also ways to script this from source to destination. See for example here. In most cases hosts in different environments will run under different accounts which is why I choose to show a prompt each time.
- Also in this script the windows group for the host is kept the same for the destination environment. This might not be the case in your particular situation.

After running this script on the destination server I have a exact copy of my host environment on the source server.

The source script looks like this:

$ScriptFile = Read-Host 'Enter full path of script file:'</pre>
'#Determine BizTalk root and switch to host container.' | Out-File $ScriptFile
'$BizTalkRoot = (get-psdrive -PsProvider BizTalk).Root' | Out-File $ScriptFile -Append
'Join-Path $BizTalkRoot ''Platform Settings\Hosts'' | Set-Location' | Out-File $ScriptFile -Append
'' | Out-File $ScriptFile -Append

'$RunningServer = $Env:ComputerName' | Out-File $ScriptFile -Append

$BizTalkRoot = (get-psdrive -PsProvider BizTalk).Root
Join-Path $BizTalkRoot 'Platform Settings\Hosts' | Set-Location

'#Create hosts' | Out-File $ScriptFile -Append
$HostArray = @()
Get-ChildItem -Path . |  Foreach-Object {
    if (!$_.IsDefault -and $_.HostType -ne 'Isolated') {
   
        $HostArray += $_.Name
   
        "#Create host '$($_.Name)' and set properties." | Out-File $ScriptFile -Append
        "New-Item -Path '$($_.Name)' -HostType '$($_.HostType)' -NtGroupName '$($_.NtGroupName)' -AuthTrusted:`$$($_.AuthTrusted)" | Out-File $ScriptFile -Append
        "Set-ItemProperty -Path '$($_.Name)' -Name HostTracking -Value $($_.HostTracking)" | Out-File $ScriptFile -Append
        "Set-ItemProperty -Path '$($_.Name)' -Name Is32BitOnly -Value $($_.Is32BitOnly)" | Out-File $ScriptFile -Append
        '' | Out-File $ScriptFile -Append
                   
    }
}

'#Switch to host instances container.' | Out-File $ScriptFile -Append
'Join-Path $BizTalkRoot ''Platform Settings\Host Instances'' | Set-Location' | Out-File $ScriptFile -Append
'' | Out-File $ScriptFile -Append

Join-Path $BizTalkRoot 'Platform Settings\Host Instances' | Set-Location

'#Create host instances' | Out-File $ScriptFile -Append
Get-ChildItem -Path . |  Foreach-Object {
    if ($HostArray -contains $_.HostName) {
      
        "#Create host instance '$($_.Name)' and set properties." | Out-File $ScriptFile -Append
        "`$Credential = `$Host.UI.PromptForCredential('Host Instance user credentials', 'Please enter credentials for host instance ''$($_.HostName)''', '', '')" | Out-File $ScriptFile -Append
        "New-Item -Path 'hostinstance' -HostName '$($_.HostName)' -RunningServer `$RunningServer -Credentials `$Credential" | Out-File $ScriptFile -Append
        "Set-ItemProperty -Path '$($_.Name)' -Name IsDisabled -Value $($_.IsDisabled)" | Out-File $ScriptFile -Append
         '' | Out-File $ScriptFile -Append
       
    }
}

In the script I skip the default and isolated host. As with the generated output script this is just a sample and might not apply to your specific situation. The source script should be modified to confirm to your requirements and environment.

You can download the source script from here.