This post was originally published here.
Microsoft BizTalk Server 2010 ships with some assemblies that assist you with the administration and deployment of your BizTalk environment. There was a small challenge to dynamically detect the BizTalk Servers of a BizTalk Group, during an automated deployment.
Microsoft BizTalk Server 2010 ships with some assemblies that assist you with the administration and deployment of your BizTalk environment. During the development of an automated deployment plan, we were able to perform most of the deployment tasks at a BizTalk application level, by using these assemblies:
Microsoft.BizTalk.ExplorerOM
- Create/delete applications
- Control receive locations
- Control orchestrations
- Control send ports
- Control send port groups
- Control application references
Microsoft.BizTalk.ApplicationDeployment
- Add/remove resources
Microsoft.BizTalk.Deployment
- Import/export bindings
Microsoft.BizTalk.Operations
- Query for active service instances
Remark that all of the used objects can be initialized by three parameters:
- SqlServerName
- BizTalkMgmtDbName
- ApplicationName
The object “BizTalk Group” is defined by the SqlServerName and the BizTalkMgmtDbName. A “BizTalk Application” is defined by its BizTalk Group and the ApplicationName. However, these assemblies have totally no notion of the object “BizTalk Server“. They only support operations at a database level (BizTalk Group), but some deployment tasks need to be executed on a BizTalk Server level:
- Install/uninstall assemblies to the Global Assembly Cache
- Control host instances
For both actions we needed to be able to dynamically determine which BizTalk Servers are part of the already defined BizTalk Group. After some research, we found two options to implement this logic:
Windows Management Instrumentation
WMI has some support for BizTalk via the WMI namespace “root\\MicrosoftBizTalkServer”. We are able to loop though all configured host instances, by executing a query on the MSBTS_HostInstance class. As each host instance runs on a BizTalk Server, it’s easy to implement some logic that retrieves all BizTalk Servers.
private List<string> GetBizTalkServers() { List<string> btsServers = new List<string>(); EnumerationOptions wmiEnumerationOptions = new EnumerationOptions { ReturnImmediately = false }; ObjectQuery wmiQuery = new ObjectQuery("SELECT * FROM MSBTS_HostInstance"); using (ManagementObjectSearcher wmiSearcher = new ManagementObjectSearcher("root\\MicrosoftBizTalkServer", wmiQuery.QueryString, wmiEnumerationOptions)) { ManagementObjectCollection hostInstanceCollection = wmiSearcher.Get(); foreach (ManagementObject hostInstance in hostInstanceCollection.Cast<ManagementObject>()) { string btsServer = hostInstance["Name"].ToString().Split(' ').Last(); if (btsServers.Contains(btsServer) == false) { btsServers.Add(btsServer); } } } return btsServers; }
Custom SQL Server query
Another option is to retrieve the information directly from the BizTalkMgmtDb. The table adm_Server actually contains a list of all BizTalk Servers that are part of the BizTalk Group. So this simple .NET code is able to return us the needed information:
private List<string> GetBizTalkServers() { List<string> btsServers = new List<string>(); SqlConnection sqlConnection = new SqlConnection(String.Format(CultureInfo.CurrentCulture, "Server={0};Database={1};Integrated Security=SSPI;", SqlServerName, MgmtDatabase)); SqlCommand sqlCommand = new SqlCommand("SELECT Name FROM [dbo].[adm_Server]", sqlConnection); sqlConnection.Open(); SqlDataReader sqlDataReader = sqlCommand.ExecuteReader(); while (sqlDataReader.Read()) { btsServers.Add(sqlDataReader["Name"].ToString()); } sqlConnection.Close(); return btsServers; }
Conclusion
It’s pretty easy to retrieve a list of all BizTalk Servers that are part of a BizTalk Group. A limitation of the WMI approach is that this will only work when it’s executed on one of the BizTalk Servers. So I prefer the SQL approach, because this will also work for remote execution.