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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
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


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
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;
  }
 }
}