I have successfully used a custom pipeline component template twice in the past and have documented what changes are needed to the template for reuse. On the third attempt to use the template pipeline component, an error is generated. Any help with this is greatly appreciated.
I have consulted the following sources, checked and tried the various solutions to the point I understood what was being said, to no avail.
http://sandroaspbiztalkblog.wordpress.com/2009/10/16/developing-pipelines-components-unc-path-error/
http://esgraham.blogspot.com/2008/01/invalid-pipeline-component-load.html
I have tried the wizard (http://btsplcw.codeplex.com/) but upon running it, it failed with its own errors
Here are the steps performed.
A copy of the assembly is put in folder C:\Program Files (x86)\Microsoft BizTalk Server 2010\Pipeline Components. The error is received when, from Tools, Choose Toolbox Items, BizTalk Pipeline Components tab a browse and open is performed.
---------------------------
Pipeline Component Error
---------------------------
You have selected an invalid pipeline component assembly. Please check security settings for the assembly if you are loading it from an UNC path.
---------------------------
Below is my cheat-sheet for changes when using the template.
namespace ConvrtSpcsToTab
{
/// STEPS TO FOLLOW TO REUSE THIS TEMPLATE FOR A NEW PIPELINE CUSTOM COMPONENT:
/// 1. Generate a new GUID for this project template. Go to menu bar, select Tools, Create GUID,
/// option 6. Paste generated GUID over existing GUID at the two occurrences of GUID in the
/// code below.
/// 2. Change [ComponentCategory(CategoryTypes.???)] to needed Component Category.
/// 3. Change namespace ??? to new namespace.
/// 4. Change public class ??? to new class name.
/// 5. Change System.Resources.ResourceManager("???", to agree with new namespace and new class name
///
[System.Runtime.InteropServices.Guid("78BD3D3C-BBF2-471E-B6EA-993E5F0EB4F7")]
[ComponentCategory(CategoryTypes.CATID_Encoder)]
public class CvSpToTab : Microsoft.BizTalk.Component.Interop.IComponent, IBaseComponent, IPersistPropertyBag, IComponentUI
{
private System.Resources.ResourceManager resourceManager = new System.Resources.ResourceManager("ConvrtSpcsToTab.CvSpToTab", Assembly.GetExecutingAssembly());
. . .
public void GetClassID(out System.Guid classid)
{
classid = new System.Guid("78BD3D3C-BBF2-471E-B6EA-993E5F0EB4F7");
}
. . .
}
}
Here is the assembly information (AssemblyInfo.cs)
using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; // General Information about an assembly is controlled through the following // set of attributes. Change these attribute values to modify the information // associated with an assembly. [assembly: AssemblyTitle("ConvrtSpcsToTab.csproj")] [assembly: AssemblyDescription("Trim out all spaces and insert a tab")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("UofMiami")] [assembly: AssemblyProduct("ConvrtSpcsToTab.csproj")] [assembly: AssemblyCopyright("Copyright 2012")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] // Setting ComVisible to false makes the types in this assembly not visible // to COM components. If you need to access a type in this assembly from // COM, set the ComVisible attribute to true on that type. [assembly: ComVisible(false)] // The following GUID is for the ID of the typelib if this project is exposed to COM [assembly: Guid("bc6f5d4c-d8e9-431e-a834-9183f3d20273")] // Version information for an assembly consists of the following four values: // // Major Version // Minor Version // Build Number // Revision // // You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] [assembly: AssemblyVersion("1.0.0.0")] [assembly: AssemblyFileVersion("1.0.0.0")]
In the ConvrtSpacsToTab project, Properties, Build Events, Post-build event command line, the following was added to register the project in the assembly GAC_MSIL.
CALL "%VS100COMNTOOLS%vsvars32.bat" > null
gacutil.exe /i "$(TargetPath)"
Here is the full listing of the class component (ConvrtSpcsToTab.cs).
using System; using System.IO; using System.Linq; using System.Text; using System.Drawing; using System.Resources; using System.Reflection; using System.Diagnostics; using System.Collections; using System.Collections.Generic; using System.ComponentModel; using Microsoft.BizTalk.Message.Interop; using Microsoft.BizTalk.Component.Interop; using Microsoft.BizTalk.Component; using Microsoft.BizTalk.Messaging; namespace ConvrtSpcsToTab { /// STEPS TO FOLLOW TO REUSE THIS TEMPLATE FOR A NEW PIPELINE CUSTOM COMPONENT: /// 1. Generate a new GUID for this project template. Go to menu bar, select Tools, Create GUID, /// option 6. Paste generated GUID over existing GUID at the two occurrences of GUID in the /// code below. /// 2. Change [ComponentCategory(CategoryTypes.???)] to needed Component Category. /// 3. Change namespace ??? to new namespace. /// 4. Change public class ??? to new class name. /// 5. Change System.Resources.ResourceManager("???", to agree with new namespace and new class name /// [System.Runtime.InteropServices.Guid("78BD3D3C-BBF2-471E-B6EA-993E5F0EB4F7")] [ComponentCategory(CategoryTypes.CATID_Encoder)] public class CvSpToTab : Microsoft.BizTalk.Component.Interop.IComponent, IBaseComponent, IPersistPropertyBag, IComponentUI { private System.Resources.ResourceManager resourceManager = new System.Resources.ResourceManager("CvSpToTab.ConvrtSpcsToTab", Assembly.GetExecutingAssembly()); #region IBaseComponent members /// <summary> /// Name of the component /// </summary> [Browsable(false)] public string Name { get { return resourceManager.GetString("COMPONENTNAME", System.Globalization.CultureInfo.InvariantCulture); } } /// <summary> /// Version of the component /// </summary> [Browsable(false)] public string Version { get { return resourceManager.GetString("COMPONENTVERSION", System.Globalization.CultureInfo.InvariantCulture); } } /// <summary> /// Description of the component /// </summary> [Browsable(false)] public string Description { get { return resourceManager.GetString("COMPONENTDESCRIPTION", System.Globalization.CultureInfo.InvariantCulture); } } #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("78BD3D3C-BBF2-471E-B6EA-993E5F0EB4F7"); } /// <summary> /// not implemented /// </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) { } /// <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) { } #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 ((System.Drawing.Bitmap)(this.resourceManager.GetObject("COMPONENTICON", System.Globalization.CultureInfo.InvariantCulture))).GetHicon(); } } /// <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) { // example implementation: // ArrayList errorList = new ArrayList(); // errorList.Add("This is a compiler error"); // return errorList.GetEnumerator(); 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) { string bodyNew = ""; IBaseMessagePart bodyPart = inmsg.BodyPart; if (bodyPart != null) { Stream originalStream = bodyPart.GetOriginalDataStream(); if (originalStream != null) { StreamReader reader = new StreamReader(originalStream); string body = reader.ReadToEnd(); string[] split = body.Split(new Char[] { ' ', ',', '\t' }); foreach (string s in split) { if (s.Trim() != "") bodyNew = bodyNew + s.Trim() + '\t'; } MemoryStream ms = new MemoryStream(); StreamWriter writer = new StreamWriter(ms); writer.AutoFlush = true; writer.Write(bodyNew); ms.Position = 0; inmsg.BodyPart.Data = ms; reader.Close(); } } return inmsg; } #endregion } }Thanks.