In the last release of the BizTalk Deployment Framework, an additional feature was
added that I thought deserved its own post for explanation…
If you are responsible for troubleshooting BizTalk applications in production, you
are likely hungry for all the information you can get about why something is failing.
Since all BizTalk project assemblies are in the GAC, the stack traces you
get (either from your own logging, or the event logs BizTalk generates for unhandled
exceptions) do not contain file and line number information. This makes post-mortem
analysis a lot harder…
A new custom NAnt task (getgacpath) and corresponding support within BizTalkDeploymentInclude.nant
was added for placing PDB (program database) files for all BizTalk and component assemblies
into the GAC. (You can use just this NAnt task without the rest of the Deployment
Framework, of course. In addition, a standalone command line utility called
GetGacPath has been included in the “Tools” download.)
Why is this interesting? Well, because it allows you to get stack traces that
include file and line number information even when assemblies reside in the GAC.
(This is obviously useful and useable outside the domain of BizTalk…) Without
extra work, file and line number information is generally missing from a stack
trace if a PDB file is not co-located physically with the corresponding assembly.
Putting the PDB file directly into the GAC is an easy way of solving this problem.
Set the “deployPDBsToGac” NAnt property to “true” in your project-specific NAnt file
to get this functionality.
A couple of points are worth mentioning:
If the directory structure of the GAC were to ever change, this would need to be updated.
(See my upcoming post on using this technique with .NET 2.0.)
- It would be great if Gacutil.exe provided this functionaity, but it doesn’t.
You should strongly consider having your release-mode binaries (aka ‘deployment’ configuration
in BizTalk) build PDB files – there is no reason not to. Look under Project
properties/Configuration properties/Build/Generate Debugging Information.
Stack traces that show up in the event log either through your own logging, or via
BizTalk (because the exception was unhandled) will now have file and line number info.
For orchestrations, the file name will correspond to the temporary C# file generated
at compile time. If you use the techniques described in this
post , you can correlate back to the actual statement that failed. For instance,
the event log might say:
 ERROR BizTalkSample.Orchestrations.TopLevelOrch - An exception was caught. [a08701ff-bf80-4940-9f9f-c2bb8597684b] System.Exception: Something exceptional happened. at BizTalkSample.Orchestrations.TopLevelOrch.segment2(StopConditions stopOn) in c:\Documents and Settings\Scott\Local Settings\Temp\h0li3wbi.0.cs:line 2538
If you grab the file mentioned (h0li3wbi.0.cs) using BTSFileDump (again,see here)
you can cross-reference this message to a location in the generated C# code for TopLevelOrch:
You might save off “h0li3wbi.0.cs” (the temp file name chosen when TopLevelOrch compiled) and
the other generated files when you do your build, using BTSFileDump. (That would be
tough to do if you build with CruiseControl, etc.) But you wouldn’t have to
do that – if you can retrieve the source code used for a particular deployment,
then the line number alone should be sufficient to get you to the exception
site (since you can find the correct temp file by looking for comments, etc. that
are in the orchestration – just like if you were using this
technique to do live debugging.) This all gets better with BizTalk 2006
– see a future post on this topic.
Final point: If you set deployPDBsToGac to “true”, deployments will begin by stopping
the BizTalk services (instead of just bouncing the services at the end.) The
reason for this is that the BTSNTSvc.exe process will not “let go” of an assembly
for which it has loaded a PDB file (so you have to terminate it.) This means
you may not always want this switch on for the developer edit/run/debug cycle.