May 282011
 

If you get the following error when configuring BAM tools for BizTalk 2010:

Microsoft SQL Server 2008 Data Transformation Services (DTS) for BAM Archiving is not installed on the local machine.  Please install Microsoft SQL Server 2008 Integration Services. (Microsoft.BizTalk.Bam.CfgExtHelper.ToolsHelper)
For help, advice click: http://go.microsoft.com/fwlink/events.asp?ProdName=Microsoft+BizTalk+Server+2009&ProdVer=3.8.368.0&EvtSrc=Microsoft.BizTalk.Bam.CfgExtHelper.ToolsHelper&EvtID=error_DTS2008Archive
——————————
ADDITIONAL INFORMATION:
Could not load file or assembly ‘Microsoft.SqlServer.ManagedDTS, Version=10.0.0.0, Culture=neutral, PublicKeyToken=89845dcd8080cc91? or one of its dependencies. The system cannot find the file specified. (Microsoft.BizTalk.Bam.CfgExtHelper)

It has to do with installing BizTalk 2010 with a remote SQL 2008 server.  Here’s the fix.

Install the Management Tools (Basic & Complete) SQL 2008 features as shown in the screenshot onto the BizTalk 2010 server:

image

Apr 042011
 

I have a trading partner who sends in invalid characters within a REF03 in an X12 850.  In the following example, viagra 40mg my element separator is *, no rx and the customer is sending in a * within the REF03.  I’m wanting to remove that invalid character before it hits the EDI pipeline component.

Example X12 850:

DTM*010*20110329~
PO1*10547090*1*EA*67.5**BP*PG7058SP—-~
PID*F****LDY FAITH INDIVIDUAL IRON~
REF*TC**HEREISMYINVALIDCHARACTER*~

I first captured all the TC Qualified Ref Segments into named groups (pre, text, and post) with the following Regular Expression.

@”(?<pre>REF*TC**)(?<text>.*?)(?<post>~)”

Using a method I am able to capture all the REF*TC segments, evaluate each one, and within each “text” group replace the errant * with “ “.  Note the use of the MatchEvaluator delegate within the Replace method.

private string myGoodString(string strBadString, string strSegmentTerminator)
        {
            string strRegex = @”(?<pre>REF*TC**)(?<text>.*?)(?<post>”+strSegmentTerminator+”)”;
            RegexOptions myRegexOptions = RegexOptions.None;
            Regex myRegex = new Regex(strRegex, myRegexOptions);

            string result = myRegex.Replace(strBadString, delegate(Match m)
            {
                return String.Join(String.Empty, new String[]{
                m.Groups[“pre”].Value,
                m.Groups[“text”].Value.Replace(“*”,” “),
                m.Groups[“post”].Value
            });

            });
            return result;
        }

Here is the resulting X12 850 snippet.

DTM*010*20110329~
PO1*10547090*1*EA*67.5**BP*PG7058SP—-~
PID*F****LDY FAITH INDIVIDUAL IRON~
REF*TC**HEREISMYINVALIDCHARACTER~

Jan 052011
 

Wanted to put a couple of scripts I put together on how to start and stop host instances using WMI in a VBS file

StartAllInProcessHostInstance
const HostInstServiceState_Stopped=1
Sub StartAllInProcessHostInstance ()
   On Error Resume Next
   Dim Query, HostInstSet, Inst
   ' Enumerate all InProcess type Host Instance
   Query = "SELECT * FROM MSBTS_HostInstance WHERE HostType =1 and IsDisabled='FALSE'"
   Set HostInstSet = GetObject("Winmgmts:!root\MicrosoftBizTalkServer").ExecQuery(Query)
   For Each Inst in HostInstSet
      ' If host instance is stopped, then it'll start it
      If( Inst.ServiceState=HostInstServiceState_Stopped ) Then
         wscript.echo "Starting host instance -> " & Inst.HostName
             Inst.Start   ' Calling MSBTS_HostInstance::Start() method
         CheckWMIError
         wscript.echo Inst.HostName & " has been started successfully on server " & Inst.RunningServer & VBNewLine
      End If
   Next
end Sub
'This subroutine deals with all errors using the WbemScripting object.  Error descriptions
'are returned to the user by printing to the console.
Sub   CheckWMIError()
   If Err <> 0   Then
      On Error Resume   Next
      Dim strErrDesc: strErrDesc = Err.Description
      Dim ErrNum: ErrNum = Err.Number
      Dim WMIError : Set WMIError = CreateObject("WbemScripting.SwbemLastError")
      If ( TypeName(WMIError) = "Empty" ) Then
         wscript.echo strErrDesc & " (HRESULT: "   & Hex(ErrNum) & ")."
      Else
         wscript.echo WMIError.Description & "(HRESULT: " & Hex(ErrNum) & ")."
         Set WMIError = nothing
      End   If
      wscript.quit 0
   End If
End Sub

StopAllInProcessHostInstance
const HostInstServiceState_Started=4
Sub StopAllInProcessHostInstance ()
   On Error Resume Next
   Dim Query, HostInstSet, Inst
   ' Enumerate all InProcess type Host Instance
   Query = "SELECT * FROM MSBTS_HostInstance WHERE HostType =1 and IsDisabled='FALSE'"
   Set HostInstSet = GetObject("Winmgmts:!root\MicrosoftBizTalkServer").ExecQuery(Query)
   For Each Inst in HostInstSet
      ' If host instance is stopped, then it'll start it
      If( Inst.ServiceState=HostInstServiceState_Started ) Then
         wscript.echo "Stopping host instance -> " & Inst.HostName
             Inst.Stop   ' Calling MSBTS_HostInstance::Stop() method
         CheckWMIError
         wscript.echo Inst.HostName & " has been stopped successfully on server " & Inst.RunningServer & VBNewLine
      End If
   Next
end Sub
'This subroutine deals with all errors using the WbemScripting object.  Error descriptions
'are returned to the user by printing to the console.
Sub   CheckWMIError()
   If Err <> 0   Then
      On Error Resume   Next
      Dim strErrDesc: strErrDesc = Err.Description
      Dim ErrNum: ErrNum = Err.Number
      Dim WMIError : Set WMIError = CreateObject("WbemScripting.SwbemLastError")
      If ( TypeName(WMIError) = "Empty" ) Then
         wscript.echo strErrDesc & " (HRESULT: "   & Hex(ErrNum) & ")."
      Else
         wscript.echo WMIError.Description & "(HRESULT: " & Hex(ErrNum) & ")."
         Set WMIError = nothing
      End   If
      wscript.quit 0
   End If
End Sub
Dec 312010
 

I have been configuring servers lately and have come across an issue that wasn’t clear.

I needed to enable network discovery, link so I simply went to the advanced sharing center
Advanced Sharing Center

I was unable to keep the sharing active.

I realized that I needed to ensure that the following services were running:

  • Function Discovery Resource Publication
    SSDP Discovery
    UPnP Device Host

Also, viagra 100mg I wanted to see ping requests, order so I enabled the following in the Advanced Firewall settings:

PING Requests

Nov 022010
 

Every once in a while I need a little C# method to do some dirty work.  Here is an example of how to use Regular Expressions to match Windows style filemask matching.

private bool FitsMask(string fileName, string fileMask)
{
    string pattern =
         ‘^’ +
         System.Text.RegularExpressions.Regex.Escape(fileMask.Replace(“.”, “__DOT__”)
                         .Replace(“*”, “__STAR__”)
                         .Replace(“?”, “__QM__”))
             .Replace(“__DOT__”, “[.]”)
             .Replace(“__STAR__”, “.*”)
             .Replace(“__QM__”, “.”)
         + ‘$’;
    return new System.Text.RegularExpressions.Regex(pattern, System.Text.RegularExpressions.RegexOptions.IgnoreCase).IsMatch(fileName);
}

Here is the pure C# method of doing the same thing.

/// <summary>
/// Filemask can be “*|[*]filenamepart[*].*|[*]extpart[*]”
/// </summary>
/// <param name=”fileName” ></param>
/// <param name=”fileMask” ></param>
/// <returns>Boolean</returns>
/// <remarks>
/// Handles positional start and/or ending wildcards.
/// </remarks>
private bool FileMatchesMask(string fileName, string fileMask)
{
   const string asterisk = “*”;
   string se = string.Empty;
   if (fileMask.Equals(“*.*”))
      return true;

   // first, get comparable filenames and extensions
   string fn = Path.GetFileNameWithoutExtension(fileName).ToLower();
   string ext = Path.GetExtension(fileName).Replace(“.”, se).ToLower();

   string maskName = Path.GetFileNameWithoutExtension(fileMask).ToLower();
   string maskExt = Path.GetExtension(fileMask).ToLower().Replace(“.”, se);
   string maskExtStripped = maskExt.ToLower().Replace(asterisk, se);
   string maskNameStripped = maskName.ToLower().Replace(asterisk, se);
   wcPos fnWCP = GetWildCardPosition(maskName);
   wcPos extWCP = GetWildCardPosition(maskExt);

   if (maskExt.Equals(asterisk))
   {
     // ext can be anything, but fn may be masked
     if (maskName.IndexOf(asterisk) > -1)
     {
      // fn masked, ck position of wildcard
      switch (fnWCP)
      {
          case wcPos.wrap:
          return IsValueMatch(fn, maskNameStripped, wcPos.wrap);
          case wcPos.start:
          return IsValueMatch(fn, maskNameStripped, wcPos.start);
          case wcPos.@end:
          return IsValueMatch(fn, maskNameStripped, wcPos.@end);
          default:
          return IsValueMatch(fn, maskNameStripped, wcPos.wrap);
      }
     }
     else
     {
      // need exact match on filename, any ext is ok
      if (maskName.Equals(fn))
          return true;
     }
   }
   else if (maskName.Equals(asterisk))
   {
     // fn can be anything, but ext may be masked
     if (maskExt.IndexOf(asterisk) > -1)
     {
      // ext masked, ck position of wildcard
      switch (extWCP)
      {
          case wcPos.wrap:
          return IsValueMatch(ext, maskExtStripped, wcPos.wrap);
          case wcPos.start:
          return IsValueMatch(ext, maskExtStripped, wcPos.start);
          case wcPos.@end:
          return IsValueMatch(ext, maskExtStripped, wcPos.@end);
          default:
          return IsValueMatch(ext, maskExtStripped, wcPos.wrap);
      }
     }
     else
     {
      // need exact match on ext, any filename is ok
      if (maskExt.Equals(ext))
          return true;
     }
   }
   else
   {
     // here neither fn or ext = asterisk so must ck for
          // existence of asterisk in either
     // b/c of position of * this will get hairy…
     if (extWCP != wcPos.none)
     {
      // ext is masked, ck for masking in fn
      if (maskName.IndexOf(asterisk) > -1)
      {
          // ext and fn are masked
          return IsValueMatch(fn, maskNameStripped, fnWCP) &
                         IsValueMatch(ext, maskExtStripped, extWCP);
      }
      else
      {
          // fn not masked, look for fn exact match and
                  // ext masked
          if (fn.Equals(maskName) &&
                     IsValueMatch(ext, maskExtStripped, extWCP))
            return true;
      }
     }
     else
     {
      // ext is not masked, requires exact ext
               // and ck for fn masking
      if (maskName.IndexOf(asterisk) > -1)
      {
          // fn masked
          if (IsValueMatch(fn, maskNameStripped, fnWCP) &&
                     ext.Equals(maskExtStripped))
            return true;
          else if (fn.Equals(maskName) &&
                           ext.Equals(maskExtStripped))
            return true;
      }
     }
   }
   return false;
}

Aug 202010
 

I needed to find the total purchase order amount given the quantity and line item price on an X12 850 using XSLT and .NET to transform XML into HTML.

In my case:

PO102 = Quantity

PO104 = Price

Add the following to the stylesheet declaration:

xmlns:msxsl=”urn:schemas-microsoft-com:xslt”

for example:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:ns0="http://schemas.microsoft.com/BizTalk/EDI/X12/2006" xmlns:msxsl="urn:schemas-microsoft-com:xslt" xmlns:var="http://schemas.microsoft.com/BizTalk/2003/var" exclude-result-prefixes="msxsl var userCSharp" xmlns:userCSharp="http://schemas.microsoft.com/BizTalk/2003/userCSharp>">

In your XSLT use the following code, modifying the referenced node and element within your XML

<xsl:variable name="tmpTotal"> <total_amount> <xsl:for-each select="ns0:PO1Loop1"> <item> <xsl:value-of select="ns0:PO1/PO102 * ns0:PO1/PO104"/> </item> </xsl:for-each> </total_amount> </xsl:variable> <total> <!--<xsl:variable name="myTotal" select="msxsl:node-set($tmpTotal)"/>--> <xsl:variable name="myTotal" select="$tmpTotal"/> <xsl:value-of select="sum(msxsl:node-set($myTotal)/total_amount/item)" /> </total>

Apr 282009
 

Recently I got the following error while trying to write out a flat file.  The way I resolved it was to remove the .dll from the GAC and resinstall the .msi.

Event Type:    Error
Event Source:    XLANG/s
Event Category:    None
Event ID:    10025
Date:        4/28/2009
Time:        12:01:17 PM
User:        N/A
Computer:    YOURCOMPUTER

Description:
Uncaught exception (see the ‘inner exception’ below) has suspended an instance of service YOURPROCESSNAME’.
The service instance will remain suspended until administratively resumed or terminated.
If resumed the instance will continue from its last persisted state and may re-throw the same unexpected exception.
InstanceId: 3f85458e-35c0-4f56-bce9-c4dc7a054f5f
Shape name: Send msg_FlatFile
ShapeId: 65a1739e-9b12-41c2-abb1-1aa2776d2657
Exception thrown from: segment 1, progress 22
Inner exception: Failed while attempting to send message ‘msg_FlatFile’.
Exception type: SendFailedException
Source: Microsoft.XLANGs.BizTalk.Engine
Target Site: Void WriteMessageState(Microsoft.BizTalk.Interop.IBTPEPInfoLookup, System.Guid, Microsoft.XLANGs.BaseTypes.XLANGMessage, Microsoft.XLANGs.Core.Segment, System.String, System.String, System.Collections.IList, Boolean, System.Collections.IList)
The following is a stack trace that identifies the location where the exception occured

   at Microsoft.BizTalk.XLANGs.BTXEngine.BTXXlangStore.WriteMessageState(IBTPEPInfoLookup pepLookup, Guid portId, XLANGMessage msg, Segment seg, String opname, String url, IList promoteProps, Boolean track, IList toPromote)
   at Microsoft.BizTalk.XLANGs.BTXEngine.BTXLogicalPortBinding.SendMessage(XLANGMessage msg, XlangStore store, Segment seg, OperationInfo op, IList additionalProps, IList toPromote, Boolean ignoreRoutingFailure)
   at Microsoft.BizTalk.XLANGs.BTXEngine.BTXPortBase.SendMessage(Int32 iOperation, XLANGMessage msg, Correlation[] initCorrelations, Correlation[] followCorrelations, Context cxt, Segment seg, ActivityFlags flags)
   at YOURORCH.segment1(StopConditions stopOn)
   at Microsoft.XLANGs.Core.SegmentScheduler.RunASegment(Segment s, StopConditions stopCond, Exception& exp)
Additional error information:

        Exception from HRESULT: 0xC0C01672
Exception type: COMException
Source: Microsoft.XLANGs.BizTalk.Engine
Target Site: Void PostToSendPort(System.Guid ByRef, Microsoft.BizTalk.Agent.Interop.IBTMessageBatch, Microsoft.BizTalk.Agent.Interop.IBTMessage, System.String, System.String, Microsoft.BizTalk.Interop.IBTMMessageList ByRef)
The following is a stack trace that identifies the location where the exception occured

   at Microsoft.BizTalk.Interop.IBTPEPInfoLookup.PostToSendPort(Guid& sendPortID, IBTMessageBatch batch, IBTMessage msg, String operationName, String url, IBTMMessageList& dlMsgList)
   at Microsoft.BizTalk.XLANGs.BTXEngine.BTXXlangStore.WriteMessageState(IBTPEPInfoLookup pepLookup, Guid portId, XLANGMessage msg, Segment seg, String opname, String url, IList promoteProps, Boolean track, IList toPromote)

For more information, see Help and Support Center at http://go.microsoft.com/fwlink/events.asp.