using System; using System.IO; using System.Text; using System.ComponentModel; using Microsoft.BizTalk.Component.Interop; using Microsoft.BizTalk.Message.Interop; namespace Company.BizTalk.PipelineComponents { /// <summary> /// Archive an incoming message. /// </summary> [ComponentCategory(CategoryTypes.CATID_PipelineComponent)] [System.Runtime.InteropServices.Guid("CFBF459C-01FC-49B8-903B-2DE65A000FF6")] [ComponentCategory(CategoryTypes.CATID_Decoder)] public class ArchivingComponentIncoming : Microsoft.BizTalk.Component.Interop.IComponent, IBaseComponent, IPersistPropertyBag, IComponentUI { #region Properties /// <summary> /// Boolean indicating if we want to archive the messages coming through this /// pipeline. /// </summary> private bool _doArchiving; /// <summary> /// Boolean indicating if we want to archive the messages coming through this /// pipeline. /// </summary> public bool DoArchiving { get { return _doArchiving; } set { _doArchiving = value; } } /// <summary> /// Location where we want to archive the messages. /// </summary> private string _archivePath; /// <summary> /// Location where we want to archive the messages. /// </summary> public string ArchivePath { get { return _archivePath; } set { _archivePath = value; } } #endregion #region IBaseComponent members /// <summary> /// Name of the component /// </summary> [Browsable(false)] public string Name { get { return "ArchivingComponentIncoming"; } } /// <summary> /// Version of the component /// </summary> [Browsable(false)] public string Version { get { return "1.0.0.0"; } } /// <summary> /// Description of the component /// </summary> [Browsable(false)] public string Description { get { return "Component used to archive incoming messages."; } } #endregion #region IPersistPropertyBag members /// <summary> /// Gets class ID of component for usage from unmanaged code. /// </summary> /// <param name="classid"> /// Class ID of the component /// </param> public void GetClassID(out System.Guid classid) { classid = new System.Guid("CFBF459C-01FC-49B8-903B-2DE65A000FF6"); } /// <summary> /// Not needed. /// </summary> public void InitNew() { } /// <summary> /// Loads configuration properties for the component. /// </summary> /// <param name="pb">Configuration property bag.</param> /// <param name="errlog">Error status.</param> public virtual void Load(Microsoft.BizTalk.Component.Interop.IPropertyBag pb, int errlog) { object val = null; // Get configuration property for indication if we want to archive val = this.ReadPropertyBag(pb, "DoArchiving"); if (val != null) { this._doArchiving = ((bool)(val)); } // Get configuration property for path where we want to archive val = this.ReadPropertyBag(pb, "ArchivePath"); if (val != null) { this._archivePath = ((string)(val)); } } /// <summary> /// Saves the current component configuration into the property bag. /// </summary> /// <param name="pb">Configuration property bag.</param> /// <param name="fClearDirty">Not used.</param> /// <param name="fSaveAllProperties">Not used.</param> public virtual void Save(Microsoft.BizTalk.Component.Interop.IPropertyBag pb, bool fClearDirty, bool fSaveAllProperties) { this.WritePropertyBag(pb, "DoArchiving", this.DoArchiving); this.WritePropertyBag(pb, "ArchivePath", this.ArchivePath); } #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 #endregion #region IComponentUI members /// <summary> /// Component icon to use in BizTalk Editor. /// </summary> [Browsable(false)] public IntPtr Icon { get { return IntPtr.Zero; } } /// <summary> /// The Validate method is called by the BizTalk Editor during the build of /// a BizTalk project. /// </summary> /// <param name="obj">An Object containing the configuration properties. /// </param> /// <returns>The IEnumerator enables the caller to enumerate through a /// collection of strings containing error messages. /// These error messages appear as compiler error messages. /// To report successful property validation, the method should return /// an empty enumerator.</returns> public System.Collections.IEnumerator Validate(object obj) { return null; } #endregion #region IComponent members /// <summary> /// Implements IComponent.Execute method. /// </summary> /// <param name="pc">Pipeline context.</param> /// <param name="inmsg">Input message.</param> /// <returns>Original input message.</returns> /// <remarks> /// IComponent.Execute method is used to initiate the processing of the /// message in this pipeline component. /// </remarks> public Microsoft.BizTalk.Message.Interop.IBaseMessage Execute( Microsoft.BizTalk.Component.Interop.IPipelineContext pc, Microsoft.BizTalk.Message.Interop.IBaseMessage inmsg) { // Check if we want to archive the message if (_doArchiving) { // Get the message that was received IBaseMessage passedMessage = inmsg; // The name under which we want to archive the message string archiveFileName = null; // Get the interchange id from the message string interchangeID = (string)passedMessage.Context.Read( "InterchangeID", "http://schemas.microsoft.com/BizTalk/2003/system-properties"); // If the transport type if file or ftp, get the incoming filename // to use as part of the archive filename (for easier identification) string filePath = null; // Get the type of adapter that was used for receiving the file string adapterType = (string)passedMessage.Context.Read( "InboundTransportType", "http://schemas.microsoft.com/BizTalk/2003/system-properties"); // Check if we received over a file adapter if (adapterType == "FILE") { filePath = (string)passedMessage.Context.Read("ReceivedFileName", "http://schemas.microsoft.com/BizTalk/2003/file-properties"); } // Check if we received over a ftp adapter else if (adapterType == "FTP") { filePath = (string)passedMessage.Context.Read("ReceivedFileName", "http://schemas.microsoft.com/BizTalk/2003/ftp-properties"); } // Set the name under which we want to archive the message archiveFileName = interchangeID + ".out"; // Check if filePath was set if (filePath != null) { // We ran into problems where the pipeline could not be executed, // and the file just kept being archived // To make sure this does not happen, we decided to never // archive the same message more then 100 times (still allowing // for multiple tests with the same message) if (Directory.GetFiles(this._archivePath, String.Format("{0}*", Path.GetFileName(filePath))).Length > 100) { goto Finished; } // If filepath was set, add the incoming file name to the file // name under which we want to archive archiveFileName = String.Format("{0}_{1}", Path.GetFileName(filePath), archiveFileName); } // Write the archive file WriteToFile(passedMessage, Path.Combine(this._archivePath, archiveFileName)); } Finished: // Continue processing the message return inmsg; } /// <summary> /// This method is used to copy the contents from a memory stream to a /// filestream, saving the contents to a file. /// </summary> /// <param name="input">The memory stream.</param> /// <param name="output">The file stream.</param> protected void CopyStream(Stream input, Stream output) { // Set the buffer size for reading the stream int BUFFER_SIZE = 4096; // Create a buffer byte[] buffer = new byte[BUFFER_SIZE]; // Integer indicating how many bytes we have read int bytesRead; try { // Read from the input stream bytesRead = input.Read(buffer, 0, BUFFER_SIZE); // Read all the bytes in the input stream while (bytesRead > 0) { // Write the contents to the output stream output.Write(buffer, 0, bytesRead); // Go to the next byte bytesRead = input.Read(buffer, 0, BUFFER_SIZE); } } catch (Exception ex) { throw ex; } finally { // Rewind input stream if (input.CanSeek) { input.Position = 0; } } } /// <summary> /// Write the contents of the message to an archive file. /// </summary> /// <param name="message">The message that should be archived.</param> /// <param name="fileName">The filename for the archive message.</param> protected void WriteToFile(IBaseMessage message, string fileName) { // Get the body of the message Stream msgStream = message.BodyPart.GetOriginalDataStream(); // Create a new file stream FileStream fileStream = null; try { // Open the archive file for writing fileStream = new FileStream(fileName, FileMode.OpenOrCreate); // Copy the data from the message to the archive file this.CopyStream(msgStream, fileStream); } catch (Exception ex) { throw ex; } finally { // Close the file stream if (fileStream != null) { fileStream.Close(); } // Close the message if (msgStream.CanSeek) { msgStream.Position = 0; } } } #endregion } } |
maandag 5 maart 2012
BizTalk 2009 Archive Incoming Messages
At one of our customers we want to be able to archive all messages that come in to BizTalk 2009. I created a pipeline component that does this, where archiving can be turned on or off from the BizTalk Administrator Console. Here is the code to do this.
Abonneren op:
Reacties posten (Atom)
Geen opmerkingen:
Een reactie posten