You may find that you want to access the tracked messages in the Microsoft BizTalk MessageBox database or in your archives. The ability to enumerate over the list of messages and to retrieve contextual and payload data about individual messages was not provided in Microsoft BizTalk Server 2004.
This hotfix adds the new MessageArchive object. The MessageArchive object exposes the ability to retrieve an enumeration over the tracked message bodies in the MessageBox database or in a custom archive database.
Note This hotfix is included in Microsoft BizTalk Server 2004 Service Pack 1.
How to obtain the latest BizTalk Server 2004 service pack
No prerequisites are required
You do not have to restart your computer after you apply this hotfix
Hotfix replacement information
This hotfix does not replace any other hotfixes
The English version of this hotfix has the file attributes (or later file attributes) that are listed in the following table. The dates and times for these files are listed in Coordinated Universal Time (UTC). When you view the file information, it is converted to local time. To find the difference between UTC and local time, use the Time Zone tab in the Date and Time item in Control Panel.
You can reference the Microsoft.BizTalk.MessageBoxOM.dll file to archive message body data in the Tracking_Spool1 and Tracking_Spool2 tables in the MessageBox database. To do this, follow these steps:
Reference the Microsoft.BizTalk.MessageBoxOM.dll file. The Microsoft.BizTalk.MessageBoxOM.dll file is located in the Global Assembly Cache (GAC). You cannot add a reference to a component that is located in the GAC in Microsoft Visual Studio .NET 2003 projects. To reference the Microsoft.BizTalk.MessageBoxOM.dll file in a Visual Studio .NET 2003 project, use one of the following methods:
Method 1: Extract the Microsoft.BizTalk.MessageBoxOM.dll file from the GAC
To extract the Microsoft.BizTalk.MessageBoxOM.dll file from the GAC, run the following command at a command prompt. In this command, DestinationPath represents a file location on the hard disk. For example, you can use the following command to extract the Microsoft.BizTalk.MessageBoxOM.dll file to the folder that contains the files for your Visual Studio .NET 2003 project:
Method 2: Manually edit the Visual Studio .NET 2003 project file
To add a reference to a component that is located in the GAC, manually edit the Visual Studio .NET 2003 project file in a text editor. For example, the .csproj and .btproj files are project files. Add the following code example to the Reference element in the project file.
Name = "Microsoft.BizTalk.MessageBoxOM"
AssemblyName = "Microsoft.BizTalk.MessageBoxOM"
HintPath = "<SystemRoot>\assembly\GAC\Microsoft.BizTalk.MessageBoxOM\18.104.22.168__31bf3856ad364e35\Microsoft.BizTalk.MessageBoxOM.dll"
Create a console application in Visual Studio .NET 2003. Then, add references to the following components in the console application:
Note Only add a reference to the Microsoft.biztalk.messageboxom.dll file if you extract the file to a location on the hard disk in step 1.
\Microsoft BizTalk Server 2004\Microsoft.BizTalk.Messaging.dll
\Microsoft BizTalk Server 2004\Microsoft.BizTalk.Pipeline.dll
Add code to the console application that lets you archive message body data. Then, compile the application. For example, use code that resembles the following Microsoft Visual C# code example.
/// Summary description for Class1.
/// The main entry point for the application.
static void Main(string args)
MessageArchive archive = new MessageArchive();
archive.ConnectionString = "Persist Security Info=False;Integrated Security=SSPI;database=BizTalkMsgboxDb;server=."
foreach (IBaseMessage msg in archive.Messages)
int cnt = msg.PartCount;
msg.GetSize(out lSize, out fImplemented);
//Trace.WriteLine("Message ID: " + msg.MessageID.ToString());
//Trace.WriteLine("Message Size: " + lSize.ToString());
Console.WriteLine("Message ID: " + msg.MessageID.ToString());
Console.WriteLine("Message Size: " + lSize.ToString());
IBaseMessagePart part = msg.GetPartByIndex(0, out partName);
Stream data = part.Data;
string contentType = part.ContentType;
string charset = part.Charset;
//byte arr = new byte[data.Length];
//data.Read(arr, 0, (int)data.Length);
//file.Write(arr, 0, (int)data.Length);
FileStream file = new FileStream(@"<full path of where you want to store the tracked messages>\" + msg.MessageID + ".xml", FileMode.Create);
byte arr = new byte;
int bytesRead = 0;
while ( (bytesRead = data.Read(arr, 0, 1024) ) > 0)
file.Write(arr, 0, bytesRead);
if (bytesRead < 1024)
Run the console application. When you run the console application, the console application retrieves tracked message body data from the inactive table in the MessageBox database. The inactive table is either the Tracking_Spool1 table or the Tracking_Spool2 table. The MessageArchive object cannot access the active table.
By default, the Tracking_Spool1 table is the active table. Therefore, no data is returned the first time that you run the console application. To make the Tracking_Spool2 table the active table, run the TrackingSpool_Cleanup_BizTalkMsgBoxDb job in SQL Server.
Note By default, the TrackingSpool_Cleanup_BizTalkMsgBoxDb job is not enabled. The TrackingSpool_Cleanup_BizTalkMsgBoxDb job deletes message body data.
After you run the TrackingSpool_Cleanup_BizTalkMsgBoxDb job, run the console application to archive the message body data in the Tracking_Spool1 table.
Note Because the TrackingSpool_Cleanup_BizTalkMsgBoxDb job purges message body data from the inactive, you must run the console application before you run the TrackingSpool_Cleanup_BizTalkMsgBoxDb job again,
For example, follow these steps to archive message body data in the MessageBox database:
Establish a schedule for archiving message body data. For example, if you run the TrackingSpool_Cleanup_BizTalkMsgBoxDb job one time every two weeks, you will have two weeks of data for message body data tracking.
Run the TrackingSpool_Cleanup_BizTalkMsgBoxDb job. The first time that you run this job, the Tracking_Spool2 table is marked as the active table. The Tracking_Spool2 table is empty. Therefore, no data is lost.
Run the console application to archive the message body data that is stored in the Tracking_Spool1 table.
When you want to archive message body data again, run the TrackingSpool_Cleanup_BizTalkMsgBoxDb job. This job purges the data that is in the Tracking_Spool1 table and marks the Tracking_Spool1 table as active.
Run the console application to archive the message body data that is stored in the Tracking_Spool2 table.
Repeat steps 4a-4e according to the schedule that you establish in step 4a.
For more information about the TrackingSpool_Cleanup_BizTalkMsgBoxDb job, click the following article number to view the article in the Microsoft Knowledge Base:
The Tracking_Spool1 or Tracking_Spool2 tables in the BiztalkMsgBoxDb database become very large in BizTalk Server 2004
MessageArchive object interfaces
The MessageArchive object implements the following interfaces:
public int CommandTimeout
Description: With this interface, the user can get and set the timeout that is associated with the underlying SQL connections.
Boundary conditions: The timeout should be more than or equal to 0. The maximum timeout will be one hour. 0 indicates an infinite timeout.
Error cases: Invalid values will generate an ArgumentOutOfRangeException exception.
public string ConnectionString
Description: With this interface, the user can get and set the connection string for the underlying archive database.
Boundary conditions: The string must not be null and must not be an empty string. After you set the connection one time successfully, you cannot reset the connection property.
Error cases: A null string or zero (0) length string causes an ArgumentException exception. Setting the property after it has already been set causes an InvalidOperationException exception. If the string is not a valid connection, SQL generates a connection exception.
public int BatchSize
Description: With this interface, the user can get and set the size of the batches of data to retrieve from the database. This action prevents BizTalk Server from using too much memory at any one time. The default value is 50.
Boundary conditions: The BatchSize must be more than or equal to 0. A BatchSize of 0 means that the MessageArchive object should retrieve all data, up to the maximum number of matches. The maximum BatchSize is 1000 because it does not make sense to load more than that in memory.
Error cases: BatchSizes that are outside the acceptable range generate an ArgumentOutOfRangeException exception.
public int MaxMatches
Description: With this interface, the user can get and set the maximum number of messages that are retrieved for the enumeration. This interface differs from the BatchSize interface in that MaxMatches is the total number of messages before the MoveNext method of the enumeration returns false.
Boundary conditions: MaxMatches must be more than or equal to 0. A value of 0 means retrieve all messages.
Error cases: If the value of MaxMatches is less than 0, an ArgumentOutOfRangeException exception is generated.
public DateTime From
Description: With this interface, the user can filter the set of messages that they would want to retrieve based on a certain date and time range. Setting this property indicates that the MessageArchive object should only retrieve messages that are published at or after the specified date and time.
Boundary conditions: If the Until time has already been specified, the From time must be equal to or before the Until time.
Error cases: If the From time is later than the Until time, an ArgumentException exception is generated.
public DateTime Until
Description: With this interface, the user can filter the set of messages that they would want to retrieve based on a certain date and time range. Setting this property indicates the MessageArchive object should only retrieve messages that are published at or before the specified time.
Boundary conditions: If the From time has already been specified, the Until time must be equal to or after the From time.
Error cases: If the Until time is before the From time, an ArgumentException exception is generated.
public IEnumerable Messages
Description: With this interface, the user can retrieve an interface that they can enumerate all the messages over. An enumeration is used because no Count property is provided.
Boundary conditions: This interface takes no parameters.
Error cases: If the connection has not yet been set, an InvalidOperationException exception is generated. All other errors are caused by SQL connectivity issues.
The Messages enumeration returns objects of type ArchivedMessage. These objects can be cast into IBaseMessage interfaces. For more information about IBaseMessage, see the Microsoft BizTalk Server 2004 online documentation.
All the following functions or methods are not supported by the MessageArchive object and will generate InvalidOperationException exceptions:
public void AddPart(string partName, IBaseMessagePart part, [MarshalAs(UnmanagedType.Bool)] bool bBody)
public IBaseMessagePart GetPart(string partName)
public void RemovePart(string partName)
public Exception GetErrorInfo()
public void SetErrorInfo(Exception errInfo)
Also included in this hotfix are some new properties that you can use in BizTalk Server solutions:
The AdapterReceiveCompleteTime property is populated when a message is received from the adapter and before the receive pipeline starts processing the message.
The AdapterTransmitBeginTime property is populated before the adapter starts transmitting the message.
The AdapterTransmitCompleteTime property is populated after the adapter successfully transmits the message. This property is not supported for the BizTalk Message Queuing Adapter (MSMQT).
These properties belong to the following namespace: