Friday, May 13, 2005

Biztalk 2004 Terminate Suspended Biztalk Messages (code nostalgia)

This posting is also initiated by me finding an old backup hard disk containing backup of code going back to 1996. It is quite fun to read through the code for 2 reasons

  1.  Most of the code would not be composed today as it was back then due to new tools of the trade and due to becoming a more mature programmer along the way.
  2. It shows a snapshot in time of how the different languages have evolved.
 This small program was created by me based on the code sample on MSDN Resuming Suspended Service Instances of a Specific Orchestration Using WMI. I was in 2004 new to Biztalk 2004 development. Not due to the fact that Biztalk 2004 came out that year but due to never having worked with Biztalk before. 

While learning Biztalk I ended up having a lot and lot of suspended messages possibly due to frequent re deployments and I needed a program to take care of this rather than just using Health and Activity Tracking.

So by building on the before mentioned MSDN code I created the following program.


With the following code behind file

using System;

using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Data;

namespace TerminateSuspendedBiztalkMessages
{
 /// <summary>
 /// Summary description for Form1.
 /// </summary>
 public class Form1 : System.Windows.Forms.Form
 {
  private System.Windows.Forms.ListBox lstHosts;
  private System.Windows.Forms.Label lblAvailableHosts;
  private System.Windows.Forms.Label lblHostName;
  private System.Windows.Forms.TextBox txtHostName;
  private System.Windows.Forms.Label lblSuspendedMessages;
  private System.Windows.Forms.TextBox txtSuspendedMessages;
  private System.Windows.Forms.Button btnTerminate;
  private System.Windows.Forms.Button btnGetSuspendedMessages;
  /// <summary>
  /// Required designer variable.
  /// </summary>
  private System.ComponentModel.Container components = null;

  public Form1()
  {
   //
   // Required for Windows Form Designer support
   //
   InitializeComponent();

   //
   // TODO: Add any constructor code after InitializeComponent call
   //
  }

  /// <summary>
  /// Clean up any resources being used.
  /// </summary>
  protected override void Dispose( bool disposing )
  {
   if( disposing )
   {
    if (components != null) 
    {
     components.Dispose();
    }
   }
   base.Dispose( disposing );
  }

  #region Windows Form Designer generated code
  /// <summary>
  /// Required method for Designer support - do not modify
  /// the contents of this method with the code editor.
  /// </summary>
  private void InitializeComponent()
  {
   this.lstHosts = new System.Windows.Forms.ListBox();
   this.lblAvailableHosts = new System.Windows.Forms.Label();
   this.lblHostName = new System.Windows.Forms.Label();
   this.txtHostName = new System.Windows.Forms.TextBox();
   this.lblSuspendedMessages = new System.Windows.Forms.Label();
   this.txtSuspendedMessages = new System.Windows.Forms.TextBox();
   this.btnTerminate = new System.Windows.Forms.Button();
   this.btnGetSuspendedMessages = new System.Windows.Forms.Button();
   this.SuspendLayout();
   // 
   // lstHosts
   // 
   this.lstHosts.HorizontalScrollbar = true;
   this.lstHosts.Location = new System.Drawing.Point(8, 32);
   this.lstHosts.Name = "lstHosts";
   this.lstHosts.Size = new System.Drawing.Size(176, 199);
   this.lstHosts.TabIndex = 0;
   this.lstHosts.SelectedIndexChanged += new System.EventHandler(this.lstHosts_SelectedIndexChanged);
   // 
   // lblAvailableHosts
   // 
   this.lblAvailableHosts.Location = new System.Drawing.Point(8, 16);
   this.lblAvailableHosts.Name = "lblAvailableHosts";
   this.lblAvailableHosts.TabIndex = 1;
   this.lblAvailableHosts.Text = "Available hosts";
   // 
   // lblHostName
   // 
   this.lblHostName.Location = new System.Drawing.Point(208, 16);
   this.lblHostName.Name = "lblHostName";
   this.lblHostName.TabIndex = 2;
   this.lblHostName.Text = "Host name:";
   // 
   // txtHostName
   // 
   this.txtHostName.BorderStyle = System.Windows.Forms.BorderStyle.None;
   this.txtHostName.Location = new System.Drawing.Point(280, 16);
   this.txtHostName.Name = "txtHostName";
   this.txtHostName.ReadOnly = true;
   this.txtHostName.Size = new System.Drawing.Size(152, 13);
   this.txtHostName.TabIndex = 3;
   this.txtHostName.TabStop = false;
   this.txtHostName.Text = "";
   // 
   // lblSuspendedMessages
   // 
   this.lblSuspendedMessages.Location = new System.Drawing.Point(208, 40);
   this.lblSuspendedMessages.Name = "lblSuspendedMessages";
   this.lblSuspendedMessages.Size = new System.Drawing.Size(120, 23);
   this.lblSuspendedMessages.TabIndex = 4;
   this.lblSuspendedMessages.Text = "Suspended Messages:";
   // 
   // txtSuspendedMessages
   // 
   this.txtSuspendedMessages.BorderStyle = System.Windows.Forms.BorderStyle.None;
   this.txtSuspendedMessages.Location = new System.Drawing.Point(328, 40);
   this.txtSuspendedMessages.Name = "txtSuspendedMessages";
   this.txtSuspendedMessages.ReadOnly = true;
   this.txtSuspendedMessages.Size = new System.Drawing.Size(104, 13);
   this.txtSuspendedMessages.TabIndex = 5;
   this.txtSuspendedMessages.TabStop = false;
   this.txtSuspendedMessages.Text = "";
   // 
   // btnTerminate
   // 
   this.btnTerminate.Location = new System.Drawing.Point(208, 104);
   this.btnTerminate.Name = "btnTerminate";
   this.btnTerminate.Size = new System.Drawing.Size(248, 23);
   this.btnTerminate.TabIndex = 6;
   this.btnTerminate.Text = "Terminate Suspended Messages";
   this.btnTerminate.Click += new System.EventHandler(this.btnTerminate_Click);
   // 
   // btnGetSuspendedMessages
   // 
   this.btnGetSuspendedMessages.Location = new System.Drawing.Point(208, 72);
   this.btnGetSuspendedMessages.Name = "btnGetSuspendedMessages";
   this.btnGetSuspendedMessages.Size = new System.Drawing.Size(248, 23);
   this.btnGetSuspendedMessages.TabIndex = 7;
   this.btnGetSuspendedMessages.Text = "Get Suspended Messages";
   this.btnGetSuspendedMessages.Click += new System.EventHandler(this.btnGetSuspendedMessages_Click);
   // 
   // Form1
   // 
   this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
   this.ClientSize = new System.Drawing.Size(472, 245);
   this.Controls.Add(this.btnGetSuspendedMessages);
   this.Controls.Add(this.btnTerminate);
   this.Controls.Add(this.txtSuspendedMessages);
   this.Controls.Add(this.lblSuspendedMessages);
   this.Controls.Add(this.txtHostName);
   this.Controls.Add(this.lblHostName);
   this.Controls.Add(this.lstHosts);
   this.Controls.Add(this.lblAvailableHosts);
   this.Name = "Form1";
   this.Text = "Form1";
   this.Load += new System.EventHandler(this.Form1_Load);
   this.ResumeLayout(false);

  }
  #endregion

  /// <summary>
  /// The main entry point for the application.
  /// </summary>
  [STAThread]
  static void Main() 
  {
   Application.Run(new Form1());
  }

  private void Form1_Load(object sender, System.EventArgs e)
  {
   this.lstHosts.DataSource = BiztalkHelper.GetHosts(Environment.MachineName);
  }

  private void lstHosts_SelectedIndexChanged(object sender, System.EventArgs e)
  {
   this.txtHostName.Text = this.lstHosts.SelectedItem.ToString();
  }

  private void btnTerminate_Click(object sender, System.EventArgs e)
  {
   this.Cursor = Cursors.WaitCursor;
   ArrayList selectedHost = new ArrayList();
   selectedHost.Add(this.lstHosts.SelectedItem.ToString());
   BiztalkHelper.TerminateMsgs(selectedHost);
   this.Cursor = Cursors.Arrow;
  }

  private void btnGetSuspendedMessages_Click(object sender, System.EventArgs e)
  {
   this.Cursor = Cursors.WaitCursor;
   this.txtSuspendedMessages.Text = BiztalkHelper.GetTotal(this.lstHosts.SelectedItem.ToString(),Environment.MachineName).ToString();
   this.Cursor = Cursors.Arrow;
  }
 }
}

and the BiztalkHelper.cs


using System;
using System.Management;
using System.Collections;

namespace TerminateSuspendedBiztalkMessages
{
 /// <summary>
 /// Summary description for BiztalkHelper.
 /// </summary>
 public class BiztalkHelper
 {
  public BiztalkHelper()
  {
   //
   // TODO: Add constructor logic here
   //
  }

  
  // First, we need to know how many Hosts there are on the machine.  
  // I created a GetHosts method that recieves the Server Name and returns the Hosts:
  public static ArrayList GetHosts(string strServer)
  {
   ArrayList strHost = new ArrayList();
   string strWQL = "SELECT * FROM MSBTS_Host";
   ManagementObjectSearcher searcherServiceInstance = new ManagementObjectSearcher (new ManagementScope (@"\\" + strServer + @"\root\MicrosoftBizTalkServer"), new WqlObjectQuery(strWQL), null);
   foreach ( ManagementObject objServiceInstance in searcherServiceInstance.Get() )
   {
    strHost.Add(objServiceInstance["Name"].ToString());
   }
   return strHost;
  }

  // Once I could see the Hosts on the machine, I queried to see if there were 
  // any Suspended Messages using GetTotal: 
   public static int GetTotal(string strHost, string strServer)
  {
   const uint SERVICE_CLASS_ORCHESTRATION = 1;

   ManagementObjectSearcher searcherServiceInstance;
   string strWQL = string.Format(
    "SELECT * FROM MSBTS_ServiceInstance WHERE ServiceClass = {0} and ServiceStatus > 2 and HostName = '{1}'", SERVICE_CLASS_ORCHESTRATION.ToString(), strHost);
   searcherServiceInstance = new ManagementObjectSearcher (new ManagementScope (@"\\" + strServer + @"\root\MicrosoftBizTalkServer"), new WqlObjectQuery(strWQL), null);

   return searcherServiceInstance.Get().Count;
  }

 
  public static int TerminateMsgs(ArrayList alHosts)
  {
   // Loop through the ArrayList and Terminate Orchestrations in each Host
   for (int intHostCount=0;intHostCount<alHosts.Count;intHostCount++)
   {
    // This will terminate all of the Service Instances
    const uint SERVICE_CLASS_ORCHESTRATION = 1;
    string strWQL = string.Format(
     "SELECT * FROM MSBTS_ServiceInstance WHERE ServiceClass = {0} and ServiceStatus > 2 and HostName = '{1}'", SERVICE_CLASS_ORCHESTRATION.ToString(), alHosts[intHostCount].ToString());
    ManagementObjectSearcher searcherServiceInstance = new ManagementObjectSearcher (new ManagementScope ("root\\MicrosoftBizTalkServer"), new WqlObjectQuery(strWQL), null);

    ArrayList ServiceClassID = new ArrayList();
    ArrayList ServiceTypeID = new ArrayList();
    ArrayList ServiceInstanceID = new ArrayList();
    string strHostQueueFullPath;
    int nNumSvcInstFound = searcherServiceInstance.Get().Count;

    // Can only terminate 2047 Instances at once.  
    // Loop through all instances and terminate 2047 at a time
    if ( nNumSvcInstFound > 0 )
    {
      
     string[] InstIdList; 
     string[] ClassIdList;
     string[] TypeIdList; 

     string strHost = string.Empty;
     string strReport = string.Empty;

     int i = 0;

     foreach ( ManagementObject objServiceInstance in searcherServiceInstance.Get() )
     {
      // It is safe to assume that all service instances belong to a single Host.
      if ( strHost == string.Empty )
       strHost = objServiceInstance["HostName"].ToString();
      if (i > 1999)
      {
       // Now have 2000 entries, so convert to an array
       ClassIdList = (string[])ServiceClassID.ToArray(typeof(string));
       TypeIdList = (string[])ServiceTypeID.ToArray(typeof(string));
       InstIdList = (string[])ServiceInstanceID.ToArray(typeof(string));

       strHostQueueFullPath = string.Format("root\\MicrosoftBizTalkServer:MSBTS_HostQueue.HostName=\"{0}\"", strHost);
       ManagementObject objHostQueue = new ManagementObject(strHostQueueFullPath);

       objHostQueue.InvokeMethod("TerminateServiceInstancesByID",
        new object[] {ClassIdList, TypeIdList, InstIdList}
       );

       // reset the Arrays
       i = 0;
       ServiceClassID.Clear();
       ServiceTypeID.Clear();
       ServiceInstanceID.Clear();
      }

      ServiceClassID.Add(objServiceInstance["ServiceClassId"].ToString());
      ServiceTypeID.Add(objServiceInstance["ServiceTypeId"].ToString());
      ServiceInstanceID.Add(objServiceInstance["InstanceID"].ToString());

      i++;
     }

     // if any of the arrays are still populated, need to terminate one last time.
     if (ServiceClassID.Count > 0)
     {
      ClassIdList = (string[])ServiceClassID.ToArray(typeof(string));
      TypeIdList = (string[])ServiceTypeID.ToArray(typeof(string));
      InstIdList = (string[])ServiceInstanceID.ToArray(typeof(string));
                        
      strHostQueueFullPath = string.Format("root\\MicrosoftBizTalkServer:MSBTS_HostQueue.HostName=\"{0}\"", strHost);
      ManagementObject objHostQueue = new ManagementObject(strHostQueueFullPath);

      objHostQueue.InvokeMethod("TerminateServiceInstancesByID",
       new object[] {ClassIdList, TypeIdList, InstIdList}
      );
     }
    }
   }

   return 0;
  }
 }
}