I’ve been doing a lot of “forensic” research on converting old systems lately. Sometimes I need to look at hundreds of ports at once, and opening each one separately to check the map is way to slow!

There are several joins required. The actual mapname is in the more generic bts_item table. You can get there by joining bt_MapSpec.

use BizTalkMgmtDb
select app.nvcName,
       sp.nvcName as SendPort, 
       item.Name as MapName,
       spt.nvcAddress, 
       bTwoWay, 
       sp.nvcSendPipelineData, 
       sp.nvcFilter
  from bts_sendport sp 
inner join bts_sendport_transport spt on spt.nSendPortID = sp.nID and spt.nTransportTypeId is not null 
inner join bts_sendport_transform spMap on spMap.nSendPortID = sp.nID 
inner join bt_MapSpec ms on ms.id = spmap.uidTransformGUID 
inner join bts_item item on ms.itemid = item.id 
inner join bts_application app on sp.nApplicationID = app.nID 
where sp.nvcName like '%210%'
order by app.nvcName, sp.nvcName 

select app.nvcName,
       rp.nvcName as ReceivePort, 
       item.Name as MapName,
       bTwoWay
from bts_receiveport rp 
inner join bts_receiveport_transform tr on tr.nReceivePortID = rp.nID 
inner join bt_MapSpec ms on ms.id = tr.uidTransformGUID 
inner join bts_item item on ms.itemid = item.id 
inner join bts_application app on rp.nApplicationID = app.nID 
where rp.nvcName like '%210%'
order by app.nvcName, rp.nvcName 

This program uses a mix of Object Explore Model (ExplorerOM) and BizTalk Provider for Powershell
to delete Send/ReceivePorts that match certain naming conventions.

We were refactoring an application and re-adding ports under a different application, so needed a script to delete the old pots.

If you run this script, I do of course suggest you run it once with the Delete Statements commented out!
Recode the selection criteria as needed for your purposes.

Parts of code from examples here: https://docs.microsoft.com/en-us/biztalk/core/receiveports-biztalk-server-sample

#===============================================================#
#=== ===#
#=== Delete the receive port named “My Receive Port” ===#
#=== ===#
#===============================================================#
Function DeleteSendPort ($sendPortName)
{
$receivePort = $catalog.ReceivePorts[$sendPortName]

if ($receivePort -ne $null)
{
$catalog.RemoveReceivePort($receivePort)

#=== Try to commit the changes made so far. If the commit fails, ===#
#=== roll back all changes in the trap handler. ===#
$catalog.SaveChanges()
}
}

Function DeleteReceivePort ($receivePortName)
{
$receivePort = $catalog.ReceivePorts[$receivePortName]

if ($receivePort -ne $null)
{
$catalog.RemoveReceivePort($receivePort)

#=== Try to commit the changes made so far. If the commit fails, ===#
#=== roll back all changes in the trap handler. ===#
$catalog.SaveChanges()
}
}

#===================#
#=== Main Script ===#
#===================#

#=== Make sure the ExplorerOM assembly is loaded ===#

[void] [System.reflection.Assembly]::LoadWithPartialName(“Microsoft.BizTalk.ExplorerOM”)

#=== Connect to the BizTalk Management database ===#

$Catalog = New-Object Microsoft.BizTalk.ExplorerOM.BtsCatalogExplorer
$MyBTSQLServer = “.” #substitute your SQL server name here
$Catalog.ConnectionString = “SERVER=$MyBTSQLServer;DATABASE=BizTalkMgmtDb;Integrated Security=SSPI”

#==================================================================#
#=== Register a trap handler to discard changes on exceptions ===#
#=== Execution will continue in the event we want to delete the ===#
#=== receive port. ===#
#==================================================================#

$Script:NoExceptionOccurred = $true
$ErrorActionPreference=”silentlycontinue”
trap
{
$Script:NoExceptionOccurred = $false
“Exception encountered:`r`n”; $_; “`r`nDiscarding changes and continuing execution so we can attempt to clean up the receive port…`r`n”
$Catalog.DiscardChanges()
}

#=== Create the new receive port ===#
#Write-Host “`r`nAttempting to create `”My Receive Port`”…”
#CreateReceivePort

# used on EDI1 to get lists of TRLG send/receive ports related to 204/990
# and create CSV file
cls
$showDate = Get-Date -DisplayHint Date
Write-Host “Started at $showDate”

Add-PSSnapIn -Name BiztalkFactory.PowerShell.Extensions #NOTE: Must be in 32-bit version of Powershell to use this SnapIn
#New-PSDrive -Name BizTalk -Root BizTalk:\ -PsProvider BizTalk -Instance EDI1-BTSDB2014\DB04 -Database BizTalkMgmtDb

Write-Host “— SendPorts —”
cd “Biztalk:\Applications\Echo.BSSR.Surface\Send Ports”
$SendPorts = Get-ChildItem
ForEach ($SendPort in $SendPorts)
{
#Write-Host $SendPort.Name $SendPort.Status
if (
($SendPort.Name.Contains(‘204’) -and $SendPort.Name.ToUpper().Contains(‘OUT’)) -or
($SendPort.Name.Contains(‘990’) -and $SendPort.Name.ToUpper().Contains(‘IN’))
)
{
## two formats of SendPorts spOutbound204XXXX and spSurfaceXXXoutbound204
Write-Host “Delete SendPort $($SendPort.Name)”
#DeleteSendPort($SendPort.Name)

}
}

Write-Host “— Receives —”
cd “Biztalk:\Applications\Echo.BSSR.Surface\Receive Ports”
$ReceivePorts = Get-ChildItem
ForEach ($ReceivePort in $ReceivePorts)
{
#Write-Host $ReceivePort.Name
if ($ReceivePort.Name.Contains(‘990’) -and $ReceivePort.Name.ToUpper().Contains(‘INBOUND’) )
{
Write-Host “Delete ReceivePort $($ReceivePort.Name )”
#DeleteReceivePort($ReceivePort.Name)

}
}

$showDate = Get-Date -DisplayHint Date
Write-Host “Completed at $showDate”

If you try to delete an application or a SendPort, you might find that SendPort is used on an EDI Trading-Partner (party).
There is no easy xref in BizTalk to show you which party might be tied to that send port. Usually the naming conventions will help, but not always.
This SQL query gives you the cross-reference.

USE BizTalkMgmtDb

SELECT 
   party.nvcname [PartyName],
   application.nvcDescription [Application],
   sendport.nvcname [SendPort]
FROM bts_sendport sendport
INNER JOIN bts_party_sendport partysendport ON partysendport.nsendportid = sendport.nid
INNER JOIN bts_party party ON partysendport.npartyid = party.nid
INNER JOIN bts_application application on application.nid = sendport.nApplicationID 
ORDER BY party.nvcname,  sendport.nvcname

You can list the cmdlets yourself with this command:

Get-Command | where { $_.ModuleName -like "BizTalk*" } 

But here is a convenient list in text format:

CommandType Name
———– —-
Cmdlet Add-ApplicationReference
Cmdlet Add-ApplicationResource
Cmdlet Deploy-Policy
Cmdlet Disable-ReceiveLocation
Cmdlet Enable-ReceiveLocation
Cmdlet Enlist-Orchestration
Cmdlet Enlist-SendPort
Cmdlet Enlist-SendPortGroup
Cmdlet Export-Application
Cmdlet Export-Bindings
Cmdlet Export-Policy
Cmdlet Get-ApplicationResourceSpec
Cmdlet Get-TrackedMessageInstance
Cmdlet Import-Application
Cmdlet Import-Bindings
Cmdlet Import-Policy
Cmdlet Remove-ApplicationReference
Cmdlet Restart-HostInstance
Cmdlet Resume-ServiceInstance
Cmdlet Set-DefaultApplication
Cmdlet Start-Application
Cmdlet Start-HostInstance
Cmdlet Start-Orchestration
Cmdlet Start-SendPort
Cmdlet Start-SendPortGroup
Cmdlet Stop-Application
Cmdlet Stop-HostInstance
Cmdlet Stop-Orchestration
Cmdlet Stop-SendPort
Cmdlet Stop-SendPortGroup
Cmdlet Terminate-ServiceInstance
Cmdlet Undeploy-Policy
Cmdlet Unenlist-Orchestration
Cmdlet Unenlist-SendPort
Cmdlet Unenlist-SendPortGroup

Reference: http://www.quicklearn.com/blog/2013/07/19/automating-and-managing-biztalk-server-2013-with-powershell/

It is also surprises me that you have to run a commandlet (like Disable-ReceiveLocation myRcvLoc) rather than calling a method on an object (such as myRcvLoc.Disable).

What seems to be missing from the list above are commands to remove items (or to create new ones).

Here are some Powershell scripts that use the ExplorerOM (Object Explorer) to do so:
https://docs.microsoft.com/en-us/biztalk/core/receiveports-biztalk-server-sample

Or to remove send ports, you can still do:

   cscript RemoveSendPort.vbs "My Business Send Port"  

The sample below shows the use of the “ForEach” and the “ForEach-Object”. I think the first method results in cleaner code. The second method using piping and the $_ to represent the anonymous object. Using Powershell ISE (Integrated Scripting Environment), both methods should give you command completion (i.e. if you type in $SendPort., you will get the property and methods names available).

cls
$showDate = Get-Date -DisplayHint Date
Write-Host "Started at $showDate" 

#NOTE: Must be in 32-bit version of Powershell to use this SnapIn
#Add-PSSnapIn -Name BiztalkFactory.PowerShell.Extensions  
#Use the line below if your SQL server is on a different machine as BizTalk - only need to run it once per Powershell "Session" 
#New-PSDrive -Name BizTalk -Root BizTalk:\ -PsProvider BizTalk -Instance MyServer\MyInstance -Database BizTalkMgmtDb


cd "Biztalk:\Applications\MyApp\Send Ports"
$SendPorts = Get-ChildItem
Write-Host "--- Method 1 ---" 
ForEach ($SendPort in $SendPorts) 
{
    Write-Host $SendPort.Name $SendPort.Status 
} 

Write-Host "--- Method 2 ---" 
Get-ChildItem -Path "Biztalk:\Applications\MyApp\Send Ports" | ForEach-Object {
   Write-Host $_.Name  $_.Status 
}

$showDate = Get-Date -DisplayHint Date
Write-Host "Completed at $showDate" 

Example of selection criteria:

cd "Biztalk:\Applications\Echo.BSSR.Surface\Send Ports"
$SendPorts = Get-ChildItem
Write-Host "--- Method 1 ---" 
ForEach ($SendPort in $SendPorts) 
{
    #Write-Host $SendPort.Name $SendPort.Status 
    if (
        ($SendPort.Name.Contains('204') -and $SendPort.Name.ToUpper().Contains('OUT')) -or 
        ($SendPort.Name.Contains('990') -and $SendPort.Name.ToUpper().Contains('IN')) 
       ) 
       {
          Write-Host "Selected " $SendPort.Name 
       }
} 

On my previous blog about using Powershell Extensions with Send/Receive Ports, I didn’t show how to do a loop.

We have a custom Rabbit-MQ adapter that has a few issues. When we restart the host-instances, the adapter may get “stuck” unless we restart the associated receive locations. So, I wrote a Powershell to restart all RabbitMQ receive locations that are currently enabled.

cls 
#
# Restart All RabbitMQ Receive Locations that are currently enabled 
#
$showDate = Get-Date -DisplayHint Date
Write-Host "Started at $showDate" 

##Add-PSSnapIn -Name BiztalkFactory.PowerShell.Extensions  #NOTE: Must be in 32-bit version of Powershellto use this SnapIn
#cd "Biztalk:\Applications\<All Artifacts>\Receive Locations"
cd "Biztalk:\Applications"
$apps = get-childitem 
# $apps = @("Echo.BSSR.Surface.LTLShipmentOut204")   # use this to limit to a list/array of specific Apps 
foreach ($app in $apps) 
{
    Write-Host "APP=$($app.Name)" 
    cd "Biztalk:\Applications\$($app.Name)\Receive Locations" 
    $rcvlocs = get-childitem  
    foreach ($rcvloc in $rcvlocs) 
    {
      if ($rcvloc.Address.Contains("rabbit")) 
          {
              Write-Host "   $($rcvloc.Name) Enabled=$($rcvLoc.Enable) " 
              if ($rcvloc.Enable -eq $TRUE)   #only restart receive locations that are started 
              {
                 Disable-ReceiveLocation $rcvloc.Name 
                 Enable-ReceiveLocation $rcvloc.Name 
                 #Write-Host "       Restarted $($rcvloc.Name)" 
                 Write-Host "       Restarted " 
              }

          }
    }
}

$showDate = Get-Date -DisplayHint Date
Write-Host "Completed at $showDate" 

One of the pains of the BizTalk Deployment Framework (BTDF) is that frequently, you build a PortBindingMaster file, then you change your port names, or make other changes, and have to rebuild it manually.

The manual process is to export the binding file, then carefully go through the file, making the changes to the BTDF variables (which have the pattern ${variableName}. You define those variables in the SettingFileGenerator.xml file (which is opened and edited as an Excel spreadsheet).

So I built a Powershell that would do the work for me. It could be more complicated, but for now, I usually only have to change my RabbitMQ host name, the SQL server and instance name, and sometimes a filename.

$appName = "MyApp" 
$exportFilename = "d:\GitMyApp_Dev\MyApp\MyApp.Deployment\PortBindingsMaster.xml"

cd "Biztalk:\Applications"
$app = get-item $appName 
export-bindings $app $exportFilename

$binding = get-content $exportFilename 
#Note: $ sign must be escaped in the replace statements 
$binding = $binding.replace("rabbit@localhost","rabbit@`${RabbitMQHostName}") 
#Note: if file has different case of string - the match will not happen 
$binding = $binding.replace("mssql://SQLEnv.dev.domain.net/db01/","mssql://`${DB01Server}/`${DB01Instance}") 
$binding = $binding.replace("mssql://.//","mssql://`${DB01Server}/`${DB01Instance}")
$binding = $binding.replace("c:\Integrations\MyApp\BizTalk2010File","`${FilePathFor2010}") 
Set-Content -Path $exportFilename -Value $binding 

 

Assumes you have installed the Powershell Extensions for BizTalk and have the:
“Add-PSSnapin BiztalkFactory.Powershell.Extensions” set up in your startup script.

It could be fancier, for example it could use RegEx to find the pattern of the SQL server name, but for now, it’s saving me a lot of time as it is.

I’m starting to write a script to build my BizTalk Deployment Framework Binding (BTDF) files. I’m planning to substite the few things that are unique with the BTDF variables. So the first step is to automate the export of the binding file.

$appName = "Echo.BSSR.FrontEnd.LTLShipmentOut" 
$bindingsDirectory = "c:\Users\NWalters\AppData\Local\BizTalk\Binding Files"
$exportFilename = "$bindingsDirectory.\$appName.xml"

cd "Biztalk:\Applications"
$app = get-item $appName 
export-bindings $app $exportFilename

 

Assumes you have installed the Powershell Extensions for BizTalk and have the:
“Add-PSSnapin BiztalkFactory.Powershell.Extensions” set up in your startup script.

When you have many BizTalk host instances and you want to do a “Debug Attach” to one specific one (for example to debug a pipeline component), it really helps to know the process ID (else you might have to attach to many host instances).

The Powershell code below conveniently lists the process ids along with the host name.
Credit for this code goes to Randal van Sputeren’s blog:

## https://biztalkmessages.wordpress.com/2010/01/05/retrieve-the-btsntsvc-exe-pid-with-powershell/
## Requires the BizTalk add-ons for Powershell 
## Alternative is: TASKLIST /FI “USERNAME ne NT AUTHORITYSYSTEM” /FI “IMAGENAME eq BTSNTSvc.exe” /SVC

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
}

GetHostPID   #call the above function 

Example Output

Debug Attach

In Visual Studio, you can attach your code to one or many BizTalk Host Instances in order to debug a helper routine or pipeline component. If you have many host instances, it’s difficult to know which one to pick. The screen below doesn’t list the Host Instance Names, only the Process IDs. So you need the Powershell command above, to xref the Host Instance to the Process ID.

I had an orchestration from a BizTalk 2010 that had the following code:


vISA06 = msg_EDI_997(EDI.ISA06);
vISA08 = msg_EDI_997(EDI.ISA08);

We were updating and refactoring to 2016. When I put that code in my 2016 orchestration, it got an error. I checked, and the EDI. fields were not showing up in the Intellinsense “drop down”.

The trick is to reference Microsoft.BizTalk.Edi.BaseArtifacts [c:\Program Files (x86)\Microsoft BizTalk Server 2013 R2\Microsoft.BizTalk.Edi.BaseArtifacts.dll] in your project, then it works fine.