BizTalk Terminator tool

When we run the Message box viewer or BizTalk health monitoring tool. then we are able to know about Biztalk database health. To clean up from unwanted and unnecessary data of database for better performance and BizTalk health maintenance. Microsoft provides this great tool named BizTalk Terminator tool.

To get more information about MessageBoxViewer click on below link:

https://vkbiztalk.com/2018/02/15/biztalk-health-monitoring-and-message-box-viewer/

The BizTalk Terminator tool allows the you to easily address common BizTalk issues via SQL, WMI, and PowerShell based tasks provided by the BizTalk team. with additional functionality including the ability to suspend, resume, and terminate in bulk by date range as well as make performance tuning changes. Integration with mbvcleanupscripts.xml from the MessageBox Viewer Utility allows Terminator to quickly resolve issues identified by MBV.

you can download this tool from below link:

https://www.microsoft.com/en-in/download/details.aspx?id=2846

BizTalk Message Box database can grow significantly by accumulating suspended messages, put in place a monitoring mechanism to identify and resolve suspended messages. When you find a database integrity problem that is causing your databases to grow use the BizTalk Terminator to resolve this.

Maintaining the health of your BizTalk databases is vital for any BizTalk environment, specially when we are talking about the BizTalkMsgBoxDb, there are several reasons for the databases to grow like suspended messages that you should avoid and resolved quickly when they happen. You can also have some integrity problems identified by using the out of the box Monitor Job or by running a tool like the Message Box Viewer, in this case you can run the BizTalk Terminator which is a tool provided by Microsoft to address these issues.

When using the Terminator tool in a Production environment, it is mandatory to stop everything (host instances, sql agent)

Terminetor.jpg

terminetor2.jpg

We can select the required option for cleanup.

 

Advertisements

BAM Activity in Custom Pipeline

Sometimes requirement cannot be fulfil by using tracking profile editor for BAM logging. Here in this code I am explaining about how to use BAM in custom pipeline. And also I am using EnableContinuation method so that we can get all the details in single row in BAM table while using different stage of BAM tracking in BizTalk application. When a solution needs BAM, and you what to link the receivedTime and sendTime together you have to use continuation.

Code for BAM Activity in Custom Pipeline:

Begin BAM Activity

This custom pipeline component can be put after xml or flat dissembler pipeline component in Receive Pipeline, because we are consuming MessageType context property to log into BAM.

For creating BAM Definition Activity please click here

https://vkbiztalk.com/2017/06/14/implementation-of-bam-activity-definition-file/

 

using System;

using System.IO;

using System.Text;

using System.Drawing;

using System.Resources;

using System.Reflection;

using System.Diagnostics;

using System.Collections;

using System.ComponentModel;

using Microsoft.BizTalk.Message.Interop;

using Microsoft.BizTalk.Component.Interop;

using Microsoft.BizTalk.Component;

using Microsoft.BizTalk.Messaging;

using System.IO;

using System.Xml;

using Microsoft.BizTalk.Bam.EventObservation;

namespace BeginBAMPipeline

{

[ComponentCategory(CategoryTypes.CATID_PipelineComponent)]

[ComponentCategory(CategoryTypes.CATID_Any)]

[System.Runtime.InteropServices.Guid(“3BB6433B-CF8D-456B-AA78-70D6788C8574”)]

public class BeginBAMPipelineComponent : IBaseComponent, IComponentUI, Microsoft.BizTalk.Component.Interop.IComponent, IPersistPropertyBag

{

#region Configuration Properties

private string _BAMActivityName;

private bool _IsTrackingRequire;

public string BAMActivityName

{

get

{

return _BAMActivityName;

}

set

{

_BAMActivityName = value;

}

}

 

public bool IsTrackingRequire

{

get

{

return _IsTrackingRequire;

}

set

{

_IsTrackingRequire = value;

}

}

 

#endregion

public string Description

{

get

{

return “Pipeline component For Begin BAM Activity”;

}

}

 

public string Name

{

get

{

return “BeginBAMPipelineComponent”;

}

}

public string Version

{

get

{

return “1.0.0.0”;

}

}

public IntPtr Icon

{

get

{

return new System.IntPtr();

}

}

public System.Collections.IEnumerator Validate(object projectSystem)

{

return null;

}

public void GetClassID(out Guid classID)

{

classID = new Guid(“3BB6433B-CF8D-456B-AA78-70D6788C8574”);

}

public void InitNew()

{

}

public virtual void Load(Microsoft.BizTalk.Component.Interop.IPropertyBag pb, int errlog)

{

object val = null;

val = this.ReadPropertyBag(pb, “BAMActivityName”);

if ((val != null))

{

this._BAMActivityName = ((string)(val));

}

val = this.ReadPropertyBag(pb, “IsTrackingRequire”);

if ((val != null))

{

this._IsTrackingRequire = ((bool)(val));

}

}

public virtual void Save(Microsoft.BizTalk.Component.Interop.IPropertyBag pb, bool fClearDirty, bool fSaveAllProperties)

{

this.WritePropertyBag(pb, “BAMActivityName”, this.BAMActivityName);

this.WritePropertyBag(pb, “IsTrackingRequire”, this.IsTrackingRequire);

}

#region utility functionality

/// <summary>

/// Reads property value from property bag

/// </summary>

/// <param name=”pb”>Property bag</param>

/// <param name=”propName”>Name of property</param>

/// <returns>Value of the property</returns>

private object ReadPropertyBag(Microsoft.BizTalk.Component.Interop.IPropertyBag pb, string propName)

{

object val = null;

try

{

pb.Read(propName, out val, 0);

}

catch (System.ArgumentException)

{

return val;

}

catch (System.Exception e)

{

throw new System.ApplicationException(e.Message);

}

return val;

}

 

/// <summary>

/// Writes property values into a property bag.

/// </summary>

/// <param name=”pb”>Property bag.</param>

/// <param name=”propName”>Name of property.</param>

/// <param name=”val”>Value of property.</param>

private void WritePropertyBag(Microsoft.BizTalk.Component.Interop.IPropertyBag pb, string propName, object val)

{

try

{

pb.Write(propName, ref val);

}

catch (System.Exception e)

{

throw new System.ApplicationException(e.Message);

}

}

#endregion

public IBaseMessage Execute(IPipelineContext pContext, IBaseMessage pInMsg)

{

IBaseMessagePart bodyPart = pInMsg.BodyPart;

StringBuilder outputMessageText = null;

XmlDocument xDoc = new XmlDocument();

 

string systemPropertiesNamespace = @”http://schemas.microsoft.com/BizTalk/2003/system-properties&#8221;;

//string messageType = “”;

if (bodyPart != null)

{

if (IsTrackingRequire)

{

Stream originalStream = bodyPart.GetOriginalDataStream();

 

if (originalStream != null)

{

string ActivityName = BAMActivityName;

string messageType = Convert.ToString(pInMsg.Context.Read(“MessageType”, systemPropertiesNamespace));

 

EventStream BAMes;

 

BAMes = pContext.GetEventStream();

 

string ActivityID = Guid.NewGuid().ToString();

string corelationToken = (string)pInMsg.Context.Read(“InterchangeID”, “http://schemas.microsoft.com/BizTalk/2003/system-properties&#8221;);

 

System.Diagnostics.EventLog.WriteEntry(“InterchangeIDStart”, corelationToken);

BAMes.BeginActivity(ActivityName, ActivityID);

BAMes.UpdateActivity(ActivityName, ActivityID, “MessageType”, messageType);

BAMes.UpdateActivity(ActivityName, ActivityID, “StartTime”, DateTime.Now);

 

BAMes.UpdateActivity(ActivityName, ActivityID, “Status”, “START”);

 

BAMes.EnableContinuation(ActivityName, ActivityID, corelationToken);

 

BAMes.EndActivity(ActivityName, ActivityID);

 

BAMes.Flush();

}

}

}

return pInMsg;

}

}

}

END Bam Activity:

This custom pipeline component can be used in any stage at in send pipeline.

using System;

using System.IO;

using System.Text;

using System.Drawing;

using System.Resources;

using System.Reflection;

using System.Diagnostics;

using System.Collections;

using System.ComponentModel;

using Microsoft.BizTalk.Message.Interop;

using Microsoft.BizTalk.Component.Interop;

using Microsoft.BizTalk.Component;

using Microsoft.BizTalk.Messaging;

using System.IO;

using System.Xml;

using Microsoft.BizTalk.Bam.EventObservation;

 

 

namespace EndBAMPipeline

{

[ComponentCategory(CategoryTypes.CATID_PipelineComponent)]

 

[ComponentCategory(CategoryTypes.CATID_Any)]

 

[System.Runtime.InteropServices.Guid(“3AC1B310-C4DF-4732-8AA9-2808349CEFFA”)]

public class EndBAMComponent : IBaseComponent, IComponentUI, Microsoft.BizTalk.Component.Interop.IComponent, IPersistPropertyBag

{

#region Configuration Properties

private string _BAMActivityName;

private bool _IsTrackingRequire;

 

public string BAMActivityName

{

get

{

return _BAMActivityName;

}

set

{

_BAMActivityName = value;

}

}

 

public bool IsTrackingRequire

{

get

{

return _IsTrackingRequire;

}

set

{

_IsTrackingRequire = value;

}

}

#endregion

 

#region IBaseComponent members

public string Description

{

get

{

return “Pipeline component For End BAM Activity”;

}

}

 

public string Name

{

get

{

return “EndBAMPipelineComponent”;

}

}

public string Version

{

get

{

return “1.0.0.0”;

 

}

 

}

#endregion

 

public IntPtr Icon

{

get

{

return new System.IntPtr();

 

}

}

public System.Collections.IEnumerator Validate(object projectSystem)

{

return null;

}

 

#region IPersistPropertyBag members

public void GetClassID(out Guid classID)

{

classID = new Guid(“3AC1B310-C4DF-4732-8AA9-2808349CEFFA”);

}

public void InitNew()

{

}

public virtual void Load(Microsoft.BizTalk.Component.Interop.IPropertyBag pb, int errlog)

{

object val = null;

val = this.ReadPropertyBag(pb, “BAMActivityName”);

if ((val != null))

{

this._BAMActivityName = ((string)(val));

}

val = this.ReadPropertyBag(pb, “IsTrackingRequire”);

if ((val != null))

{

this._IsTrackingRequire = ((bool)(val));

}

}

public virtual void Save(Microsoft.BizTalk.Component.Interop.IPropertyBag pb, bool fClearDirty, bool fSaveAllProperties)

{

this.WritePropertyBag(pb, “BAMActivityName”, this.BAMActivityName);

this.WritePropertyBag(pb, “IsTrackingRequire”, this.IsTrackingRequire);

 

}

#endregion

 

#region utility functionality

/// <summary>

/// Reads property value from property bag

/// </summary>

/// <param name=”pb”>Property bag</param>

/// <param name=”propName”>Name of property</param>

/// <returns>Value of the property</returns>

private object ReadPropertyBag(Microsoft.BizTalk.Component.Interop.IPropertyBag pb, string propName)

{

object val = null;

try

{

pb.Read(propName, out val, 0);

}

catch (System.ArgumentException)

{

return val;

}

catch (System.Exception e)

{

throw new System.ApplicationException(e.Message);

}

return val;

}

 

/// <summary>

/// Writes property values into a property bag.

/// </summary>

/// <param name=”pb”>Property bag.</param>

/// <param name=”propName”>Name of property.</param>

/// <param name=”val”>Value of property.</param>

private void WritePropertyBag(Microsoft.BizTalk.Component.Interop.IPropertyBag pb, string propName, object val)

{

try

{

pb.Write(propName, ref val);

}

catch (System.Exception e)

{

throw new System.ApplicationException(e.Message);

}

}

#endregion

public IBaseMessage Execute(IPipelineContext pContext, IBaseMessage pInMsg)

{

IBaseMessagePart bodyPart = pInMsg.BodyPart;

StringBuilder outputMessageText = null;

string systemPropertiesNamespace = @”http://schemas.microsoft.com/BizTalk/2003/system-properties&#8221;;

if (bodyPart != null)

{

if (IsTrackingRequire)

{

Stream originalStream = bodyPart.GetOriginalDataStream();

if (originalStream != null)

{

string ActivityName = BAMActivityName;

string messageType = Convert.ToString(pInMsg.Context.Read(“MessageType”, systemPropertiesNamespace));

EventStream BAMes;

BAMes = pContext.GetEventStream();

string ActivityID = “seq_” + Guid.NewGuid().ToString();

string corelationToken = (string)pInMsg.Context.Read(“InterchangeID”, “http://schemas.microsoft.com/BizTalk/2003/system-properties&#8221;);

System.Diagnostics.EventLog.WriteEntry(“InterchangeIDEND”, corelationToken);

BAMes.UpdateActivity(ActivityName, corelationToken, “EndTime”, DateTime.Now);

BAMes.UpdateActivity(ActivityName, corelationToken, “Status”, “SUCCESS”);

BAMes.EndActivity(ActivityName, corelationToken);

BAMes.Flush();

}

}

}

return pInMsg;

}

}

}

 

You can see the BAM table or BAM Portal in one row start time and end time of message in BizTalk along with status and messagetype.

Message Box Viewer

BizTalk Message Box Viewer (MBV):

BizTalk provides Message Box Viewer (MBV) tool out of box to generate report for BizTalk health and performance monitoring activity. It’s collecting details about BizTalk Server, Configuration, database and performance details.

MBV analyze in details of BizTalk MsgBox Db but also other BizTalk Dbs and generates an HTML file containing different REPORTS including a “WARNINGS REPORT” which report in yellow and red some warnings.

This tool comes along with BizTalk. When we installed BizTalk, this will available at below location:

C:\Program Files (x86)\Microsoft BizTalk Server 2013\SDK\Utilities\Support Tools\MsgBoxViewer

MBV.jpg

Dashboard and Warnings report can now be sent automatically by mail after a collect

email.jpg

Purpose of MBV:

  • Health Check tool to analyze quickly and easily a BizTalk group
  • Generates different sub-reports in HTML and plain text files
  • Targeted users : BizTalk Admins

Why MBV ?

  • Retrieve quickly maximum info from a BizTalk Production System in one click
  • Avoid sending too many queries and their usage to customers!
  • Identify all possible issues which could be critical or need attention
  • Present them in a user friendly Format
  • Emit suggestions via comments and Doc links

Features of MBV:

  • Provided in BizTalk 2013 and each next CU.
  • Support all BizTalk versions since BizTalk 2004
  • Safe to run in Production
  • No setup, just copy and run
  • Frequently used by both customers and MS engineers to check for the good health and integrity of a BizTalk group, and to retrieve a complete topology of the BizTalk Platform
  • Used by BizTalk Users to deliver Health Checks
  • Checks the integrity of BizTalk Databases and propose immediate remediation tasks to famous “Terminator” tool  (http://www.microsoft.com/en-us/download/details.aspx?id=2846)
  • Provided as both a GUI and a console application. The console version is used more and more as a custom monitoring tool to be scheduled as a task, generating periodically HTML reports but also sending periodically raised warnings in the App journal, and the warnings and dashboard in emails. It can so complement  ideally System Center Operations Manager (SCOM) and the BizTalk Mgmt Pack to provide a complete monitoring of a Production BizTalk platform
  • Query and Topology Reports
  • Support ALL versions of BizTalk including BizTalk 2K4 and 2K9
  • Can run on ANY type of Servers – SQL, XP/Vista client
  • Can analyze ALL BizTalk complex configurations  : Multiple Servers  & Multiple MsgBox databases
  • Easily Extensible (XML, DLL) – MS Internal for the moment

The goal of MBV is to retrieve the maximum amount of information from a BizTalk System in one click in the minimum amount of time, identify all possible issues which could be critical or need attention, and present them in a user friendly format.

Below is screenshot of Summary Report

mbv1.jpg

References:

https://blogs.technet.microsoft.com/jpierauc/2013/10/28/msgboxviewer-13-662-is-released-and-provides-great-new-features/

https://blogs.technet.microsoft.com/jpierauc/2007/12/20/what-is-biztalk-msgboxviewer-aka-mbv/

WCF-Custom (SQL) Receive Location Configuration with BizTalk in Multi-Server Environment

Issue:  In multi-server BizTalk environment, BizTalk WCF-Custom (SQL Binding) Receive Locations poll SQL Server more than one times instead of single polling.

Normally in multi-server BizTalk environment, we are creating host instances for each host on each BizTalk server. But BizTalk has little limitation for active/active multi-server setup.

Below are adapters which only work on single server host instance.

  • FTP
  • POP3
  • WCF-SQL (Receive Adapter)

Normally we get information on internet search about FTP and POP3 adapters for single server and forgot about mention about WCF-SQL Receive adapter. So when we deploy code on multi-server environment then we face multiple polling from WCF-SQL Receive location.

Reason: We have created two Host Instances for Host for Both BizTalk Servers and apply that host on Receive Location which is polling to Database.  So both Host instances are polling data from SQL that’s why BizTalk receive two time data.

If we apply multiple host instances on these adapters for Receive Location then every host instance will run and process data into BizTalk.

For more details you can refer to below link:

https://stackoverflow.com/questions/2165668/biztalk-receive-port-reading-twice-from-db

Resolution:

                     We can apply one of three approaches to resolve this issue. Below 2nd is mostly used in BizTalk development scenario.

  1. Create a Single Server Host Instance as Receive Handler for WCF-Custom (SQL) Receive Location
  2. In SQL, update Stored Procedure with lock for processing data and update the flag not to send any data 2nd time call until unless data is modified.
  3. Create Host Instance cluster which run on both machine. It will run as active/passive mode. If one server will unavailable then start polling with other server.

Below is link for setup for cluster Host Instances

         https://www.biztalkadmin.com/biztalk-active-active-cluster-and-msdtc/