Let's see how quickly we can put orchestration viewer functionality into a .NET application using nothing but our wits, Reflector, and Visual Studio 2005.
The HAT tool has a spiffy little orchestration debugger that displays events on the left and what appears to be a design view of the target orchestration in a pane on the right:
The image itself is interactive (as you HAT die-hards no doubt know); clicking a step will highlight it. you can also get right-click context menus on eact task and set breakpoints and perform other activities. Great stuff and someone else has already done all of the work and tested it. Even better for the lazy engineer.
To grab some of that orchestration viewer love, we need to find out where it's code lives and whether it is organized in such a way that we can reuse it. Fire up Reflector and drag a few suspicious files into it for study -- I started with the Big Kahuna, BTSHatApp.exe. After sniffing around a bit, I found something interesting:
DebugCtrl sounds perfect so I looked through the program for initialization code and an example of how it is called to render an orchestration. I assumed it would be using XSYM information (XML representing the workflow for display purposes) because I had run across XSYM with the Documentor program. I didn't find anything in the HAT application.
When my search failed, I thought about the application. How do you view an orchestration in HAT? I went and looked -- oh yeah, with the "Attach" command. So I went back to Reflector and clicked DebugCtrl to look at the method signatures for the debug control. I was rewarded with a method named Attach but it did not directly show how to load an orchestration. However, I looked at a few of the methods it called and finally found ReadSources(). It had two interesting calls:
m_sCurrentSymbols = trackingDbHelper.ReadSkedSourceFromDB(m_CurrentServiceID, m_InstID);
The method ReadSkedSourceFromDB is backed by a stored procedure call that ultimately pulls XSYM information from the database. This is the same XSYM information packed into assemblies containing orchestrations (we will return to this another day). At this point I felt like I had enough information to fire up Visual Studio .NET 2005, so I created a new C# Windows Application project named "Crow", found an appropriate free image of a corvid, then added a reference to Microsoft.BizTalk.BRMAControls. This is the assembly that contains ODViewCtrl; it can be found in <installdir>\Microsoft BizTalk Server 2006\Tracking\Control. Then I threw in some code:
// Class instance variable
private Microsoft.BizTalk.Tracking.ODViewCtrl _odViewControl;
// This goes in the constructor
_odViewControl = new ODViewCtrl();
_odViewControl.AutoScroll = true;
_odViewControl.Anchor = AnchorStyles.Top;
_odViewControl.AutoScroll = true;
_odViewControl.BackColor = Color.White;
_odViewControl.Dock = DockStyle.Fill;
_odViewControl.Enabled = true;
_odViewControl.Name = "_odViewControl";
_odViewControl.PermanentBreakpoints = true;
_odViewControl.RightToLeft = RightToLeft.No;
_odViewControl.Size = new Size(this.Size.Width, this.Size.Height);
_odViewControl.TrackedArrows = true;
_odViewControl.Visible = true; // Long XSYM content string edited; see code download
It ran the first time *cough* bs *cough* and I got the following screen:
Good but not perfect since the control feels obligated to throw a title box up with the orchestration diagram. Nice for the HAT tool but not nice for my application. I am no Windows Forms guy, but it only took me a few minutes to find the offending child control, remove it, and then adjust the remaining control's dimensions to display properly with a few lines of code:
// Remove the title label control
int x = _odViewControl.Controls.IndexOfKey("lblOdTitle");
if(x >= 0)
// Readjust the panel control containing the orch view to
// accomodate missing title label
x = _odViewControl.Controls.IndexOfKey("pnlOdCtrl");
if (x >= 0)
Control c = _odViewControl.Controls[x];
int y = c.Location.Y;
c.Location = new Point(0, 0); // change y for menu/etc
c.Size = new Size(c.Size.Width, c.Size.Height + y);
This got me what I wanted:
Now all I have to do is grab XSYM information from the database (which I'll leave as an excercise) or from an assembly (I'll address this in a future posting) and the program is somewhat useful. It would be more useful if I could dump the orchestration diagram to a jpeg...I could then use it with the Documentor and display orchestrations with other BizTalk application data. "What could be easier?" I thought.
Easy indeed. Stay tuned for the details of that folly. In the meantime, grab the bits for this project here.