<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:media="http://search.yahoo.com/mrss/"><channel><title>VSoft Technologies Blogs</title><description>VSoft Staff Blogs</description><link>http://www.finalbuilder.com/Resources/Blogs.aspx</link><item><title>Using Python in FinalBuilder</title><link>http://www.finalbuilder.com/Resources/Blogs/PostId/677/Using-Python-in-FinalBuilder.aspx</link><category>FinalBuilder</category><pubDate>Wed, 04 Jun 2008 14:00:00 GMT</pubDate><description>&lt;p&gt;Today &lt;a target="_blank" href="http://www.finalbuilder.com/forums.aspx?forumid=1&amp;amp;postid=7229&amp;amp;view=topic"&gt;FB 6.1 was released as a beta version&lt;/a&gt;. One of the major new features in this version is Python language support. We're leveraging Microsoft's &lt;a href="http://www.codeplex.com/IronPython"&gt;IronPython&lt;/a&gt; project for this, and because version 2 of IronPython is built on the Dynamic Language Runtime, we're expecting that as other DLR languages become available, we'll be able to support them in FinalBuilder as well.&lt;/p&gt;
&lt;p&gt;The Python language is pretty neat, and the fact that IronPython interacts seamlessly with the .NET Framework makes it pretty powerful by itself. It shares this feature with PowerShell.&lt;/p&gt;
&lt;p&gt;However, &lt;a target="_blank" href="http://xkcd.com/353/"&gt;what really makes Python awesome&lt;/a&gt; is the amount of extra library functionality that comes with the standard language distribution.&lt;/p&gt;
&lt;h2&gt;Example&lt;/h2&gt;
&lt;p&gt;This is a totally arbitrary example. Say your build process needs to calculate a SHA1 hash. FinalBuilder only supports MD5 at the moment. Can Python save the day?&lt;/p&gt;
&lt;h2&gt;Step One: Install Python Libraries&lt;/h2&gt;
&lt;p&gt;You need to install the Python standard libraries in order to get access to their many functions. You get this as part of the standard Windows Python distribution. Grab the "Windows Binary installer" from &lt;a target="_blank" href="http://python.org/download/"&gt;http://python.org/download/&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;Step Two: Tell FinalBuilder&lt;/h2&gt;
&lt;p&gt;You need to tell FinalBuilder where the Python library is installed. If you launch FinalBuilder and go to Tools -&amp;gt; Options -&amp;gt; FinalBuilder -&amp;gt; Script Options, as shown, you will see this options page:&lt;/p&gt;
&lt;p&gt;&lt;img alt="Script Options Frame" src="/blogimages/Python/Options.jpg" /&gt;&lt;/p&gt;
&lt;p&gt;Enter the path to the Python library directory, as shown here. The options page says you need to restart, but you actually only need to do this if you've run a Python script since you started FinalBuilder.&lt;/p&gt;
&lt;h2&gt;Step Three: Run Script Action&lt;/h2&gt;
&lt;p&gt;I use the Action filter to search for the all-purpose Run Script action, which I can then add to my project:&lt;/p&gt;
&lt;p&gt;&lt;img alt="Actions Tab" src="/blogimages/Python/ActionFilter.jpg" /&gt;&lt;/p&gt;
&lt;h2&gt;Step Four: Type in Script&lt;/h2&gt;
&lt;p&gt;Here's my SHA1 script code. I entered this in the OnExecute event, under the Script Editor tab at the bottom of the main FinalBuilder IDE. Make sure you set the script language to "Python", as shown:&lt;/p&gt;
&lt;p&gt;&lt;img alt="Script Editor view" src="/blogimages/Python/ScriptEditor.jpg" /&gt;&lt;/p&gt;
&lt;p&gt;Note that the FBVariables object behaves just like a normal Python dictionary.&lt;/p&gt;
&lt;p&gt;&lt;a href="/blogimages/Python/Python SHA1 Example.zip"&gt;Click here to download a sample project file&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;Step Five: Run it!&lt;/h2&gt;
&lt;p&gt;Here's the log output from the SHA1 Run Script:&lt;/p&gt;
&lt;p&gt;&lt;img alt="Log Output" src="/blogimages/Python/LogOutput.jpg" /&gt;&lt;/p&gt;
&lt;h2&gt;Where do I go from here?&lt;/h2&gt;
&lt;p&gt;This was a pretty basic example, but the Python library provides you with literally hundreds of similar pieces of functionality. Take a look at the &lt;a target="_blank" href="http://docs.python.org/lib/"&gt;Python Library Reference&lt;/a&gt; for a complete list.&lt;/p&gt;
&lt;h2&gt;Can't I just use the .NET Framework?&lt;/h2&gt;
&lt;p&gt;Yes! The .NET Framework also provides you with a wealth of built-in functionality. Using it from IronPython is pretty simple, too. Here's Python code that performs the same functionality, written to use the .NET Framework instead of the Python library:&lt;/p&gt;
&lt;p&gt;&lt;img alt=".NET Framework version" src="/blogimages/Python/DotNetVersion.jpg" /&gt;&lt;/p&gt;
&lt;p&gt;(It's a bit more complicated, mostly because I couldn't find a neat .NET-based way to convert a byte array to a hexadecimal string. Note that this approach does not require the Python libraries, it will work out of the box with FinalBuilder.)&lt;/p&gt;
&lt;p&gt;Both sample scripts are included in the &lt;a href="/blogimages/Python/Python SHA1 Example.zip"&gt;downloadable example&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;It would also be possible to rewrite the .NET version to use PowerShell, instead. I'll leave that as an exercise.&lt;/p&gt;</description></item><item><title>Hate Team Foundation Server?</title><link>http://www.finalbuilder.com/Resources/Blogs/PostId/676/Hate-Team-Foundation-Server.aspx</link><category>FinalBuilder,TFS</category><pubDate>Thu, 15 May 2008 14:00:00 GMT</pubDate><description>&lt;p&gt;According to Google Analytics statistics for the past month, a number of people found the FinalBuilder web site in Google search results for the query &lt;a href="http://www.google.com/search?q=hate+%22team+foundation+server%22" target="_blank"&gt;&lt;strong&gt;&lt;em&gt;hate "Team Foundation Server"&lt;/em&gt;&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;I didn't know so many people felt that way!&lt;/p&gt;
&lt;p&gt;(For the record, we think that &lt;a href="/team-foundation-server.aspx"&gt;FinalBuilder complements Team Foundation Build&lt;/a&gt; in very productive ways.)&lt;/p&gt;</description></item><item><title>Delphi: Workaround for TThread Synchronize/WaitFor Deadlock</title><link>http://www.finalbuilder.com/Resources/Blogs/PostId/675/Delphi-Workaround-for-TThread-SynchronizeWaitFor-.aspx</link><category>Delphi</category><pubDate>Wed, 23 Apr 2008 14:00:00 GMT</pubDate><description>&lt;p&gt;FinalBuilder is written in a combination of Delphi and C#. This is a blog post about a Delphi RTL threading issue that I recently ran into and had to work around.&lt;/p&gt;
&lt;p&gt;We recently had some bug reports of FinalBuilder deadlocking at shutdown under certain circumstances. I could reproduce the problem, but I was baffled for a long time because - according to the call stacks&amp;nbsp; - the program should have been fine.&lt;/p&gt;
&lt;p&gt;The issue I'd run into has been around for years, and is summed up nicely in this Borland QC note: &lt;a href="http://qc.borland.com/wc/qcmain.aspx?d=22267" target="_blank"&gt;&lt;span class="opencolor" id="MainContentUserControl__ctl0_ShortDescriptionLabel"&gt;Synchronize and WaitFor methods of TThread can lead to a DeadLock in logically correct applications&lt;/span&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;The Problem&lt;/h2&gt;
&lt;p&gt;The simple summary is: If you ever have a call stack which includes both Synchronize and WaitFor, and the thread you are waiting on also calls Synchronize at some point, you will occasionally get a deadlock.&lt;/p&gt;
&lt;p&gt;Explaining why is kind of tricky, but if you read the QC case you'll get the gist of it. The problematic sequence of events looks like this:&lt;/p&gt;
&lt;ul&gt;
    &lt;li&gt;Thread A calls Synchronize(MethodA)&lt;/li&gt;
&lt;/ul&gt;
&lt;ul&gt;
    &lt;li&gt;Thread B calls Synchronize(MethodB)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Then, inside the context of the Main Thread:&lt;/p&gt;
&lt;ul&gt;
    &lt;li&gt;Main thread calls CheckSynchronize() while processing messages&lt;/li&gt;
    &lt;li&gt;CheckSynchronize is implemented to batch-process all waiting calls(&lt;a target="_self" href="#commentary"&gt;*&lt;/a&gt;).&lt;a name="star"&gt;&lt;/a&gt; So it picks up the queue of waiting calls (containing MethodA and MethodB) and loops through them one by one.&lt;/li&gt;
    &lt;li&gt;MethodA executes in the main thread's context. Assume MethodA calls ThreadB.WaitFor&lt;/li&gt;
    &lt;li&gt;WaitFor calls CheckSynchronize to process any waiting calls to Synchronize&lt;/li&gt;
    &lt;li&gt;In theory, this should then process ThreadB's Synchronize(MethodB), allowing Thread B to complete.&lt;/li&gt;
    &lt;li&gt;However, MethodB is already a possession of the first CheckSynchronize call, so it never gets called.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;DEADLOCK!&lt;/p&gt;
&lt;h2&gt;The Solution&lt;/h2&gt;
&lt;p&gt;The ideal solution is to refactor your program so it will never call CheckSynchronize or WaitFor from inside an already-synchronized method call. For FinalBuilder, this was not a good option - all it takes is one Synchronized method call to call ProcessMessages and you're letting in dozens of potential deadlocks.&lt;/p&gt;
&lt;p&gt;The solution I came up with is to write a "SafeSynchronize" method that only allows one thread at a time to get on the Synchronize method queue. This comes with a performance hit, but prevents the deadlock.&lt;/p&gt;
&lt;p&gt;Here's a new class which implements the SafeSynchronize method:&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;TSafeSyncThread&amp;nbsp;=&amp;nbsp;class(TThread)&lt;br /&gt;
&amp;nbsp;&amp;nbsp;private&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;procedure&amp;nbsp;SafeSynchronizeInner;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;protected&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;procedure&amp;nbsp;SafeSynchronize(const&amp;nbsp;AThreadMethod:&amp;nbsp;TThreadMethod);&lt;br /&gt;
&amp;nbsp;&amp;nbsp;end;&lt;br /&gt;
&lt;br /&gt;
implementation&lt;br /&gt;
&lt;br /&gt;
{&amp;nbsp;TSafeSyncThread&amp;nbsp;}&lt;br /&gt;
&lt;br /&gt;
var&lt;br /&gt;
&amp;nbsp;&amp;nbsp;FSingleSynchronize&amp;nbsp;:&amp;nbsp;TCriticalSection;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;FSingleSynchronizeTarget&amp;nbsp;:&amp;nbsp;TThreadMethod;&lt;br /&gt;
&lt;br /&gt;
procedure&amp;nbsp;TSafeSyncThread.SafeSynchronize(const&amp;nbsp;AThreadMethod:&amp;nbsp;TThreadMethod);&lt;br /&gt;
begin&lt;br /&gt;
&amp;nbsp;&amp;nbsp;FSingleSynchronize.Acquire;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;FSingleSynchronizeTarget&amp;nbsp;:=&amp;nbsp;AThreadMethod;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;Synchronize(SafeSynchronizeInner);&lt;br /&gt;
end;&lt;/p&gt;
&lt;p &gt;
procedure&amp;nbsp;TSafeSyncThread.SafeSynchronizeInner;&lt;br /&gt;
var&lt;br /&gt;
&amp;nbsp;&amp;nbsp;targetMethod&amp;nbsp;:&amp;nbsp;TThreadMethod;&lt;br /&gt;
begin&lt;br /&gt;
&amp;nbsp;&amp;nbsp;targetMethod&amp;nbsp;:=&amp;nbsp;FSingleSynchronizeTarget;&lt;br /&gt;
&amp;nbsp;&amp;nbsp;FSingleSynchronize.Release;&amp;nbsp;//&amp;nbsp;Now&amp;nbsp;we're&amp;nbsp;inside&amp;nbsp;a&amp;nbsp;CheckSynchronize&amp;nbsp;call,&amp;nbsp;it's&amp;nbsp;safe&amp;nbsp;to&amp;nbsp;let&amp;nbsp;another&amp;nbsp;thread&amp;nbsp;join&amp;nbsp;the&amp;nbsp;queue&lt;br /&gt;
&amp;nbsp;&amp;nbsp;targetMethod;&amp;nbsp;&amp;nbsp;&lt;br /&gt;
end;&lt;/p&gt;
&lt;p&gt;Basically, this serializes access to the Synchronize queue. The performance hit is potentially quite large if you have a lot of concurrent SafeSynchronize calls and a busy main thread. FinalBuilder is designed in a way which minimizes this, so it's less of an issue for us.&lt;/p&gt;
&lt;p&gt;I put together a quick test project which demonstrates the issue (at least on Delphi 2007.) You can get it here &lt;a href="/blogimages/WaitForDeadlockExample.zip"&gt;if you want to have a look&lt;/a&gt;. It also contains &lt;a href="/blogimages/SafeSyncThread.pas"&gt;SafeSyncThread.pas&lt;/a&gt; if you want to incorporate the workaround into your own projects. This code comes with no guarantees and no warranty, obviously.&lt;/p&gt;
&lt;p&gt;If anyone has a better (preferably faster) solution to this problem, which doesn't require rewriting the RTL, please let us know. :).&lt;/p&gt;
&lt;p&gt;PS The test project example contains some fairly awful cut-and-paste code reproduction, which - for the record - I normally avoid like the plague. I used it here because the methods are very simple, and I couldn't see an easy way to rearchitect it.&lt;/p&gt;
&lt;p&gt;&lt;a name="commentary"&gt;&lt;/a&gt;(*) FWIW, I actually quite like the way that CheckSynchronize is implemented, using an InterlockedExchange to swap the old queue object with a brand new one. That way you can process the entire old queue at once, without granular locking. Check the source code if you want to see what I mean. It's just a shame about the deadlock. (&lt;a href="#star"&gt;back&lt;/a&gt;)&lt;/p&gt;</description></item><item><title>FinalBuilder/Automise Keyboard Shortcuts</title><link>http://www.finalbuilder.com/Resources/Blogs/PostId/674/FinalBuilderAutomise-Keyboard-Shortcuts.aspx</link><category>Automise,FinalBuilder</category><pubDate>Tue, 15 Apr 2008 14:00:00 GMT</pubDate><description>&lt;p&gt;Brent was watching me fly through some FinalBuilder operations the other day and he suggested I write a blog post about the best keyboard shortcuts to use.&lt;/p&gt;
&lt;p&gt;Even as a power user/developer, you can sometimes use a tool every day and not know the best keyboard shortcuts for it. I only learned many of the keyboard shortcuts for Visual Studio after I attended a special session at TechEd last year.&lt;/p&gt;
&lt;p&gt;I don't want to drown you in information here, so I'm going to list four shortcuts that are essential to know,&lt;strong&gt; &lt;/strong&gt;and another four that are very useful.&lt;/p&gt;
&lt;h2&gt;Essential&lt;/h2&gt;
&lt;p&gt;If you own a keyboard and use FinalBuilder or Automise, the following keyboard shortcuts are essential. They will improve your productivity ten-fold!&lt;/p&gt;
&lt;p&gt;
&lt;/p&gt;
&lt;table width="767" height="173" cellspacing="1" cellpadding="1" border="1"&gt;
    &lt;tbody&gt;
        &lt;tr&gt;
            &lt;td&gt;&lt;strong&gt;Key&lt;/strong&gt;&lt;/td&gt;
            &lt;td&gt;&lt;strong&gt;Context&lt;/strong&gt;&lt;/td&gt;
            &lt;td&gt;&lt;strong&gt;Description&lt;/strong&gt;&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
            &lt;td&gt;&lt;span style="font-family: 'courier new';"&gt;Ctrl-&lt;/span&gt;&lt;span style="font-family: 'courier new';"&gt;I&lt;/span&gt;&lt;/td&gt;
            &lt;td&gt;Main IDE Window&lt;/td&gt;
            &lt;td&gt;
            &lt;p&gt;Focus the Actions filter field to search for a new action.&lt;br /&gt;
            If the filter field is already focused, this keystroke hides the Actions sidebar instead.&lt;sup&gt;*&lt;/sup&gt;&lt;/p&gt;
            &lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
            &lt;td&gt;&lt;span style="font-family: 'courier new';"&gt;Ctrl-Right&lt;/span&gt;&lt;/td&gt;
            &lt;td&gt;Selected action(s)&lt;/td&gt;
            &lt;td&gt;Indent the selected action(s) as new children of the action above them.&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
            &lt;td&gt;&lt;span style="font-family: 'courier new';"&gt;Ctrl-Left&lt;/span&gt;&lt;/td&gt;
            &lt;td&gt;Selected action(s)&lt;/td&gt;
            &lt;td&gt;Outdent the select action(s) relative to their parent action&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
            &lt;td&gt;&lt;span style="font-family: 'courier new';"&gt;Ctrl-Up/Down&lt;/span&gt;&lt;/td&gt;
            &lt;td&gt;Selected action(s)&lt;/td&gt;
            &lt;td&gt;Move selected action(s) up and down&lt;/td&gt;
        &lt;/tr&gt;
    &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;In my opinion, using the Ctrl-Arrow keys to rearrange actions is essential (drag and drop is just too fiddly!)&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;sup&gt;*&lt;/sup&gt; The "hide sidebar if currently focused" feature is new in FB 6.&lt;/p&gt;
&lt;h2&gt;Very Useful&lt;/h2&gt;
&lt;p&gt;The following key combinations are very useful when you are typing in a text field while editing an action:&lt;/p&gt;
&lt;p&gt;
&lt;/p&gt;
&lt;table width="767" cellspacing="1" cellpadding="1" border="1"&gt;
    &lt;tbody&gt;
        &lt;tr&gt;
            &lt;td&gt;&lt;strong&gt;Key&lt;/strong&gt;&lt;/td&gt;
            &lt;td&gt;&lt;strong&gt;Description&lt;/strong&gt;&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
            &lt;td&gt;&lt;span style="font-family: 'courier new';"&gt;F3&lt;br /&gt;
            &lt;/span&gt;&lt;/td&gt;
            &lt;td&gt;Define a new variable on-the-fly.&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
            &lt;td&gt;&lt;span style="font-family: 'courier new';"&gt;F2&amp;nbsp;&lt;/span&gt;&lt;/td&gt;
            &lt;td&gt;Pop up an advanced edit dialog with lists of variables, PropertySets, etc.&amp;nbsp;&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
            &lt;td&gt;&lt;span style="font-family: 'courier new';"&gt;F12&lt;/span&gt;&lt;/td&gt;
            &lt;td&gt;Pop up a list of &lt;a href="http://www.finalbuilder.com/blogs.aspx?EntryID=251"&gt;suggested variable replacements&lt;/a&gt;.&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
            &lt;td&gt;&lt;span style="font-family: 'courier new';"&gt;Ctrl-Space&amp;nbsp;&lt;/span&gt;&lt;/td&gt;
            &lt;td&gt;Automatic completion for variable and PropertySet names.&amp;nbsp;&lt;/td&gt;
        &lt;/tr&gt;
    &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;For FB 6, we also did a lot of work on the Tabbing behaviour in the IDE. You should be able to use Tab to navigate the main IDE elements very easily.&lt;/p&gt;</description></item><item><title>FinalBuilder 6 - Output Monitors</title><link>http://www.finalbuilder.com/Resources/Blogs/PostId/673/FinalBuilder-6-Output-Monitors.aspx</link><category>FinalBuilder</category><pubDate>Thu, 03 Apr 2008 14:00:00 GMT</pubDate><description>&lt;h2&gt;Introduction&lt;/h2&gt;
&lt;p&gt;&amp;nbsp;Output Monitors give you a quick way to watch action output and change the behaviour of the action depending on what you see. This lets you extend built-in actions in powerful ways.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2&gt;Sample Project&lt;/h2&gt;
&lt;p&gt;Unlike my normal "pie in the sky" examples, this one is based on a real problem. This morning we had a customer in our chatroom who had a problem deploying to QA:&lt;/p&gt;
&lt;blockquote&gt;when a user's connection to the database breaks, or if a user is accessing some of the files in QA and connected to a different database (different to the one we are checking against) the FinalBuilder project will try and deploy the files and get a sharing violation which causes the build to fail&lt;/blockquote&gt;
&lt;p&gt;&lt;strong&gt;Summary&lt;/strong&gt;: the customer needed a way to tell if one or more files were open on a remote machine.&lt;/p&gt;
&lt;h2&gt;SysInternals Tools Are Awesome&lt;/h2&gt;
&lt;p&gt;SysInternals make PsTools and a raft of other excellent Windows "power administrator tools". If you haven't checked them out, &lt;a target="_blank" href="http://technet.microsoft.com/en-us/sysinternals"&gt;you should&lt;/a&gt;. It's no wonder that Microsoft bought the company.&lt;/p&gt;
&lt;p&gt;For my solution to the above problem, I made use of two great SysInternals tools:&lt;/p&gt;
&lt;ul&gt;
    &lt;li&gt;&lt;a target="_blank" href="http://technet.microsoft.com/en-us/sysinternals/bb897553.aspx"&gt;PsExec&lt;/a&gt; (part of PsTools) can deploy and run an executable on a remote machine. There's a PsExec action built into FinalBuilder, although you still need to download and install PsTools.&lt;/li&gt;
    &lt;li&gt;&lt;a target="_blank" href="http://technet.microsoft.com/en-us/sysinternals/bb896655.aspx"&gt;Handle&lt;/a&gt; is a great little command line tool that dumps (among other things) all of the open files on a system. An excellent debugging aid.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2&gt;The Plan&lt;/h2&gt;
&lt;p&gt;Use PsExec to deploy and execute handle.exe on the remote computer, and use FinalBuilder to scan the output for the file(s) we need to check for.&lt;/p&gt;
&lt;h2&gt;The Project&lt;/h2&gt;
&lt;p&gt;Here's the complete project, including my verbose comments. Because of the powerful Output Monitor (and the awesome Sysinternals tools), almost everything happens inside the PsExec action:&lt;/p&gt;
&lt;p&gt;&lt;img alt="Check Remote Open File project" src="/blogimages/OutputMonitors4.png" /&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2&gt;Output Monitor&lt;/h2&gt;
&lt;p&gt;To check for our file(s), we need to configure an Output Monitor on the PsExec action. We have two variables:&lt;/p&gt;
&lt;ul&gt;
    &lt;li&gt;fileName - The filespec or filename that we want to check for. This variable is set by the user.&lt;/li&gt;
    &lt;li&gt;fileInUse - The details of the file that's in use, if there is one. This variable is set when the PsExec action runs.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Every action in FinalBuilder 6 has an option on the Runtime tab called "Monitor Action Output":&lt;/p&gt;
&lt;p&gt;&lt;img alt="Runtime Property Tab" align="middle" src="/blogimages/OutputMonitors1.png" style="vertical-align: middle;" /&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Click the button to edit the Output Monitors for that action:&lt;/p&gt;
&lt;p&gt;&lt;img alt="Output Monitors Dialog with one monitor" src="/blogimages/OutputMonitors2.png" /&gt;&lt;/p&gt;
&lt;p&gt;For our monitor (shown above), we're checking for any content which contains %fileName% and saving the first match to the variable fileInUse.&lt;/p&gt;
&lt;p&gt;There are lots of other options for output monitor behaviour. Click on the dropdown for a full list:&lt;/p&gt;
&lt;p&gt;&lt;img alt="Full list of behaviours" src="/blogimages/OutputMonitors3.png" /&gt;&lt;/p&gt;
&lt;p&gt;... For example, if we wanted a list of all matching lines, we could use the "Save All Matches to Variable" behaviour.&lt;/p&gt;
&lt;p&gt;As configured, the output monitor supports wildcard matching with * and ?. If we wanted it to be really powerful, we could change it to use a regular expression - grep-in-a-box!&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2&gt;Project File&lt;/h2&gt;
&lt;p&gt;You can download the FinalBuilder 6 project file &lt;a href="/blogimages/CheckRemoteOpenFile.zip"&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2&gt;Alternatives&lt;/h2&gt;
&lt;p&gt;Sometimes you need more powerful output processing, and Output Monitors are not up to the task. You can always use the OnStatusMessage script event to run some script every time the action outputs data. I actually did a &lt;a href="/blogs.aspx?EntryID=254"&gt;blog post about this&lt;/a&gt; a couple of weeks ago.&lt;/p&gt;</description></item><item><title>FinalBuilder 6 : PowerShell (Part Three, Custom Actions)</title><link>http://www.finalbuilder.com/Resources/Blogs/PostId/672/FinalBuilder-6-PowerShell-Part-Three-Custom-Acti.aspx</link><category>FinalBuilder</category><pubDate>Wed, 02 Apr 2008 14:00:00 GMT</pubDate><description>&lt;p&gt;This is the last in a series of blog posts about PowerShell support in FinalBuilder 6.&lt;/p&gt;
&lt;ul&gt;
    &lt;li&gt;&lt;a href="http://www.finalbuilder.com/blogs.aspx?EntryID=253"&gt;Part One&lt;/a&gt; showed how to use one-liners to create powerful PowerShell execute conditions.&lt;/li&gt;
    &lt;li&gt;&lt;a href="http://www.finalbuilder.com/blogs.aspx?EntryID=254"&gt;Part Two&lt;/a&gt; showed how to use PowerShell script events to parse output and change the behaviour of an action.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;For this last post, I'm going to walk through creating a custom action which scans the Event Log and reports the frequency of messages from different sources.&lt;/p&gt;
&lt;h2&gt;The Script&lt;/h2&gt;
&lt;p&gt;Here are the parts of the PowerShell script that I'm going to use to implement the new action.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;1) A custom function&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;WMI uses dmtf date formatting. This is a PowerShell function to create a dmtf datetime string representing (Now - $x hours) ago.&lt;/p&gt;
&lt;blockquote&gt; function dmtfWithin([int] $hours)&lt;br /&gt;
{&lt;br /&gt;
&amp;nbsp;&amp;nbsp;[System.Management.ManagementDateTimeconverter]::ToDmtfDateTime `&lt;br /&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;([DateTime]::Now.AddHours(- $hours))&lt;br /&gt;
}&lt;br /&gt;
&lt;/blockquote&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;2) Read Action Properties&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Action properties are loaded using the same syntax as other custom actions. If you've used ActionStudio before then this will look familiar. Coming in-the-pipeline are some CmdLets to make this look more like PowerShell and less like .NET.&lt;/p&gt;
&lt;blockquote&gt; # Set up parameters&lt;br /&gt;
$computerName = $Context.ExpandExpression($Context.Properties.PropertyAsString("ComputerName"), $True)&lt;br /&gt;
$hours = $Context.Properties.PropertyAsString("Hours")&lt;br /&gt;
&lt;/blockquote&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;3) Process Event Log&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;This is where the dirty work happens - build a WQL filter string, get the WMI objects for the event log entries, and build a hashtable mapping event source names to their frequencies. The particularly neat line is the last one with the % sign - that's shorthand for "for each".&lt;/p&gt;
&lt;blockquote&gt; # Read results&lt;br /&gt;
$filter = "TimeWritten &amp;gt; '" + (dmtfWithin($hours)) + "'"&lt;br /&gt;
$results = Get-WmiObject -computer $computerName -class Win32_NTLogEvent -filter $filter&lt;br /&gt;
$freqTable = @{}&lt;br /&gt;
$results | % { $freqTable[$_.SourceName] += 1 }&lt;br /&gt;
&lt;/blockquote&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;4) Log the Results&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Log the contents of our hash table, sorted and formatted into a table:&lt;/p&gt;
&lt;blockquote&gt;# Log Results&lt;br /&gt;
$freqTable.GetEnumerator() | sort -descending Value | ft Value, Name -autosize -wrap&lt;/blockquote&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;5) Set Result to True&lt;/strong&gt;&lt;br /&gt;
&lt;br /&gt;
The Result parameter determines whether or not to fail the action.&lt;/p&gt;
&lt;blockquote&gt;$Result = $True &lt;/blockquote&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2&gt;Creating the custom action&lt;/h2&gt;
&lt;p&gt;I recorded a screencast showing how to create the custom action in ActionStudio. &lt;a target="_blank" href="/blogimages/PowerShell/Writing.html"&gt;Click here&lt;/a&gt; to view in a new window.&lt;/p&gt;
&lt;p&gt;&lt;object width="911" height="649" codebase="http://active.macromedia.com/flash5/cabs/swflash.cab#version=7,0,0,0" classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"&gt;
&lt;param value="/blogimages/PowerShell/Writing.swf" name="movie"&gt;
&lt;param value="true" name="play"&gt;
&lt;param value="false" name="loop"&gt;
&lt;param value="transparent" name="wmode"&gt;
&lt;param value="low" name="quality"&gt; &lt;embed width="911" height="649" pluginspage="http://www.macromedia.com/shockwave/download/index.cgi?P1_Prod_Version=ShockwaveFlash" type="application/x-shockwave-flash" wmode="transparent" loop="false" quality="low" src="/blogimages/PowerShell/Writing.swf"&gt;  &lt;/object&gt; &lt;/p&gt;
&lt;h2&gt;Running the custom action&lt;/h2&gt;
&lt;p&gt;&lt;a target="_blank" href="/blogimages/PowerShell/Running.html"&gt;Click here&lt;/a&gt; to view this screencast in a new window.&lt;/p&gt;
&lt;p&gt;&lt;object width="834" height="628" codebase="http://active.macromedia.com/flash5/cabs/swflash.cab#version=7,0,0,0" classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"&gt;
&lt;param value="/blogimages/PowerShell/Running.swf" name="movie"&gt;
&lt;param value="true" name="play"&gt;
&lt;param value="false" name="loop"&gt;
&lt;param value="transparent" name="wmode"&gt;
&lt;param value="low" name="quality"&gt; &lt;embed width="834" height="628" pluginspage="http://www.macromedia.com/shockwave/download/index.cgi?P1_Prod_Version=ShockwaveFlash" type="application/x-shockwave-flash" wmode="transparent" loop="false" quality="low" src="/blogimages/PowerShell/Running.swf"&gt;  &lt;/object&gt;&lt;/p&gt;
&lt;h2&gt;Download&lt;/h2&gt;
&lt;p&gt;&lt;a href="/blogimages/PowerShell/PowerShellCustomAction.zip"&gt;Click here to download&lt;/a&gt; a zip file with the custom action package. The unzipped .fbap file needs to be saved in the ActionDefs directory inside the FinalBuilder 6 program directory.&lt;/p&gt;
&lt;h2&gt;More Resources&lt;/h2&gt;
&lt;p&gt;The example action package "FBScriptExamples.fbap" comes with FinalBuilder, and contains some more sample PowerShell actions which can be loaded in ActionStudio.&lt;/p&gt;
&lt;p&gt;The ActionStudioManual.pdf file (located in the FinalBuilder Program directory) contains a reference section with built-in custom action types and methods, and also some more information on creating PowerShell actions.&lt;/p&gt;
&lt;h2&gt;Some Notes&lt;/h2&gt;
&lt;ul&gt;
    &lt;li&gt;This is a pretty simple example, but (like the others) it is fairly simple to extend it to cover lots of other Windows-related tasks.&lt;/li&gt;
    &lt;li&gt;FYI, there is a dedicated Get-EventLog command in PowerShell. In this instance, I chose to use WMI instead because WMI can read from remote machines, and can read across all event logs. If you use the dedicated command, you need to choose a single event log to read from.&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>FinalBuilder 6 : PowerShell (Part Two, Script Events)</title><link>http://www.finalbuilder.com/Resources/Blogs/PostId/671/FinalBuilder-6-PowerShell-Part-Two-Script-Events.aspx</link><category>FinalBuilder</category><pubDate>Wed, 26 Mar 2008 05:00:00 GMT</pubDate><description>&lt;h2&gt;&amp;nbsp;PowerShell Script Events&lt;/h2&gt;
&lt;p&gt;This is Part Two in a series about the new PowerShell support in FinalBuilder 6. In &lt;a href="http://www.finalbuilder.com/blogs.aspx?EntryID=253&amp;amp;language=en-US"&gt;Part One&lt;/a&gt;, we learned how to create an action Execute Condition using PowerShell.&lt;/p&gt;
&lt;p&gt;In this article we will show how to use PowerShell as a scripting language in the FinalBuilder IDE, in order to customize the behaviour of a built-in FinalBuilder action. We'll also showcase some of the powerful string processing features in PowerShell.&lt;/p&gt;
&lt;h2&gt;Script Events&lt;/h2&gt;
&lt;p&gt;When you add an action to a FinalBuilder project, you also add at least three script events:&lt;/p&gt;
&lt;ul&gt;
    &lt;li&gt;BeforeAction - This script event is called before the action runs.&lt;/li&gt;
    &lt;li&gt;OnStatusMessage - This script event is called each time the action outputs something to the log.&lt;/li&gt;
    &lt;li&gt;AfterAction - This script event is called after the action has finished running.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;You can access the script events by clicking on the "Script Editor" tab in FinalBuilder. For this blog post, we're going to use PowerShell to create an implementation for each of these script events.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2&gt;PsLogList&lt;/h2&gt;
&lt;p&gt;I'm going use scripting to extend the built-in FinalBuilder action for the PsLogList tool. PsLogList is part of the &lt;a target="_blank" href="http://technet.microsoft.com/en-us/sysinternals/bb896649.aspx"&gt;PsTools suite from SysInternals/Microsoft&lt;/a&gt;. It dumps the contents of the event log on a local or remote machine.&lt;/p&gt;
&lt;p&gt;We're going to customize the action so it parses the list of log entries to automatically extract data about the frequency of events from different sources.&lt;/p&gt;
&lt;h2&gt;Output format&lt;/h2&gt;
&lt;p&gt;Here's an example log entry, as output from PsLogList:&lt;/p&gt;
&lt;blockquote&gt; [16664] Service Control Manager&lt;br /&gt;
Type:     INFORMATION&lt;br /&gt;
Computer: DYNAMO&lt;br /&gt;
Time:     3/03/2008 3:09:18 PM   ID:       7035 &lt;br /&gt;
User:     NT AUTHORITY\SYSTEM&lt;br /&gt;
The IMAPI CD-Burning COM Service service was successfully sent a start control.&lt;br /&gt;
&lt;/blockquote&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;For our example, the piece of data want to extract would be "Service Control Manager" in the expression above. To extract this, we can use the following Regular Expression:&lt;/p&gt;
&lt;blockquote&gt;^\[\d+\] (.+)$&lt;/blockquote&gt;
&lt;p&gt;Regular expressions are supported directly in PowerShell. You can create a regular expression using a code snippet like this:&lt;/p&gt;
&lt;blockquote&gt;$headerExpr = [regex] "\[\d+\] (.+)"&lt;/blockquote&gt;
&lt;p&gt;(If you ever need help remembering Regular Expression syntax, I recommend &lt;a target="_blank" href="http://www.regular-expressions.info/reference.html"&gt;www.regular-expressions.info&lt;/a&gt;.)&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2&gt;Hash tables&lt;/h2&gt;
&lt;p&gt;The other piece of PowerShell functionality that we're going to make use of is the hash table. We're going to create an empty PowerShell hash table, and then use it as a dictionary to store event source names along with the frequency that each source appears.&lt;/p&gt;
&lt;p&gt;Here's the script used to create a new empty hashtable:&lt;/p&gt;
&lt;blockquote&gt;$hashTable = ${}&lt;/blockquote&gt;
&lt;p&gt;To increment the frequency of an item in the table, we can use the increment operation += on the hashtable entry. If there is no entry, PowerShell returns $null, but ($null + 1) == 1 so it will work properly.&lt;/p&gt;
&lt;blockquote&gt;$hashTable[$name] += 1&lt;br /&gt;
&lt;br /&gt;
&lt;/blockquote&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2&gt;Scripting it up&lt;/h2&gt;
&lt;p&gt;Here are the complete script events: (&lt;a href="http://www.finalbuilder.com/blogimages/PowerShell Script Event Example.zip"&gt;download as project&lt;/a&gt;.)&lt;/p&gt;
&lt;h3&gt;BeforeAction Script Event&lt;/h3&gt;
&lt;blockquote&gt; # Create empty hash table for use in action (we need to store it in a Project Variable)&lt;br /&gt;
$FBVariables["FrequencyTable"] = @{ }&amp;nbsp;&lt;br /&gt;
&lt;/blockquote&gt;&lt;blockquote&gt;&lt;/blockquote&gt;
&lt;h3&gt;OnStatusMessage Script Event&lt;/h3&gt;
&lt;blockquote&gt;  # When output comes from the action, check if it is an Event header line&lt;br /&gt;
&lt;br /&gt;
$headerPattern = "^\[\d+\] (.+)$"&lt;br /&gt;
$RegexOptions = [System.Text.RegularExpressions.RegexOptions]&lt;br /&gt;
&lt;br /&gt;
foreach ( $match in [regex]::Matches( $StatusMessage.MessageText, $headerPattern, $RegexOptions::MultiLine ) )&lt;br /&gt;
{&lt;br /&gt;
&amp;nbsp;&amp;nbsp;$appName = $match.Groups[1].Value.Trim()&lt;br /&gt;
&amp;nbsp;&amp;nbsp;$freqTable = $FBVariables["FrequencyTable"]&lt;br /&gt;
&amp;nbsp; $freqTable[$appName] += 1&lt;br /&gt;
}  &lt;/blockquote&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3&gt;AfterAction Script Event&lt;/h3&gt;
&lt;blockquote&gt; # Log the frequencies, sorted by value&lt;br /&gt;
"Frequencies for different sources"&lt;br /&gt;
$FBVariables["FrequencyTable"].GetEnumerator() | sort -descending Value | ft Value, Name -autosize -wrap&lt;br /&gt;
#&lt;br /&gt;
# (the .GetEnumerator() call in the expression above is a trick which allows us to sort the contents of the hashtable.)&lt;br /&gt;
&lt;/blockquote&gt;
&lt;h2&gt;Download the Project&lt;/h2&gt;
&lt;p&gt;&lt;a href="http://www.finalbuilder.com/blogimages/PowerShell Script Event Example.zip"&gt;Click here to download a sample project with this action&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The downloaded project has one more feature: it suppresses the normal output from PsLogList. Only our custom information is shown in the log.&lt;/p&gt;
&lt;h2&gt;Action output&lt;/h2&gt;
&lt;p&gt;Here's the log output from when the action is run normally:&lt;/p&gt;
&lt;blockquote&gt;Frequencies for different sources&lt;br /&gt;
Value Name&lt;br /&gt;
----- ----&lt;br /&gt;
29 Service Control Manager&lt;br /&gt;
3 Application Popup&lt;br /&gt;
2 W32Time&lt;br /&gt;
2 IPSec&lt;br /&gt;
2 EventLog&lt;br /&gt;
2 WinHttpAutoProxySvc&lt;br /&gt;
1 DCOM&lt;br /&gt;
1 AeLookupSvc&lt;br /&gt;
1 Tcpip6&lt;br /&gt;
1 Tcpip&lt;br /&gt;
1 redbook&lt;br /&gt;
&lt;/blockquote&gt;
&lt;h2&gt;Why this is Useful&lt;/h2&gt;
&lt;p&gt;OK, so this example isn't particularly relevant for automated builds. However, this technique (or one like it) can be used to parse information from any tool which is run by FinalBuilder.&lt;/p&gt;
&lt;h2&gt;Notes&lt;/h2&gt;
&lt;ul&gt;
    &lt;li&gt;Having a script event run every time data is logged decreases the performance of the action. For actions which log very large amounts of data, it's better to use Log To Variable and then process the output all-at-once in a separate action.&lt;/li&gt;
&lt;/ul&gt;
&lt;ul&gt;
    &lt;li&gt;You'll note that the actual regular expression call used in the script event is different to the example&amp;nbsp; expression showed at the beginning. We have to call the .NET RegularExpression class directly in order to use MultiLine mode. (If anyone from the PowerShell Team is reading this, please try and find a way to set the expression mode with simpler syntax!)&lt;/li&gt;
&lt;/ul&gt;
&lt;ul&gt;
    &lt;li&gt;You can actually do everything shown in the example with JavaScript instead of PowerShell, using a Regexp object and an associative array. However, some steps (like automatically printing the results) are much more complex to do with JavaScript.&lt;/li&gt;
&lt;/ul&gt;
&lt;ul&gt;
    &lt;li&gt;You could also get the same results from a PowerShell action by using get-wmi and the Win32_NTLogEvent class. That will be the subject of upcoming blog post Part Three: Custom actions.&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>FinalBuilder 6 : PowerShell (Part One, Execute Conditions)</title><link>http://www.finalbuilder.com/Resources/Blogs/PostId/670/FinalBuilder-6-PowerShell-Part-One-Execute-Condi.aspx</link><category>FinalBuilder</category><pubDate>Tue, 18 Mar 2008 05:00:00 GMT</pubDate><description>&lt;h2&gt;Introduction&lt;/h2&gt;
&lt;p&gt;PowerShell support in FinalBuilder 5.5 was limited to the Execute PowerShell Action. For FinalBuilder 6, we've made PowerShell a "first class" scripting language, alongside JavaScript and VBScript.&lt;/p&gt;
&lt;p&gt;This is the first in a series of blog posts which show the different ways PowerShell can integrate with FinalBuilder. Today's example is the Execute Condition.&lt;/p&gt;
&lt;h2&gt;Execute Conditions&lt;/h2&gt;
&lt;p&gt;Every action in FinalBuilder has a field called the "Execute Condition", on the Runtime property page.&lt;/p&gt;
&lt;p&gt;This lets you place a single line of script which evaluates as a boolean condition. If the script evaluates "True", the action will execute. If the script evaluates "False", the action will be skipped.&lt;/p&gt;
&lt;h2&gt;PowerShell Execute Conditions&lt;/h2&gt;
&lt;p&gt;Due to it's terse but expressive syntax, PowerShell seems to lend itself to one-line expressions (a quick &lt;a href="http://www.google.com.au/search?q=PowerShell+one-liners" target="_blank"&gt;Google search&lt;/a&gt; will confirm this.) This can be great for execute conditions.&lt;/p&gt;
&lt;h2&gt;Examples&lt;/h2&gt;
&lt;p&gt;If you want an action to only run if Notepad is executing, you can use this one-line expression:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;get-Process | where {$_.name -eq "NotePad"}&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="PowerShell Execute Condition" src="/blogimages/PowerShell/PowerShellExecuteCondition.png" /&gt;&lt;/p&gt;
&lt;p&gt;If you want an action to run only if a remote computer is online, you can use this expression:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;gwmi Win32_PingStatus -Filter "Address='remotePC'" |where {$_.StatusCode -eq 0}&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;PowerShell treats any non-null value as equivalent to $True, so any result will be regarded as True, while no result will be regarded as False.&lt;/p&gt;
&lt;h2&gt;Caveats&lt;/h2&gt;
&lt;p&gt;I think one-liners are neat. It's probably because they remind me of growing up with my Apple //e and &lt;a href="http://en.wikipedia.org/wiki/Nibble_(magazine)" target="_blank"&gt;Nibble magazine's&lt;/a&gt; one-liner competition. However, like anything else, one liners can be abused. They can be the stuff of programming horror stories.&lt;/p&gt;
&lt;p&gt;My suggestions for responsible Execute Condition use:&lt;/p&gt;
&lt;ul&gt;
    &lt;li&gt;Put something in the action comment field if the Execute Condition isn't self-documenting.&lt;/li&gt;
    &lt;li&gt;Use a script event if the Execute Condition gets longer than the text field on the Runtime page.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Next - &lt;a href="http://www.finalbuilder.com/blogs.aspx?EntryID=254"&gt;Part Two : Script Events&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;( Credits : thanks to beta tester Robert for the Notepad suggestion.)&lt;/p&gt;</description></item><item><title>Team Foundation Build and FinalBuilder 6 (a match made in heaven)</title><link>http://www.finalbuilder.com/Resources/Blogs/PostId/669/Team-Foundation-Build-and-FinalBuilder-6-a-match-.aspx</link><category>FinalBuilder,TFS</category><pubDate>Fri, 14 Mar 2008 05:00:00 GMT</pubDate><description>&lt;p&gt;I just posted a new article on &lt;a href="http://www.finalbuilder.com/articles.aspx?mid=370&amp;amp;ctl=ArticleView&amp;amp;articleId=29"&gt;Integrating FinalBuilder with Microsoft Team Foundation Server&lt;/a&gt;. The article deals with the great new Team Build integration in FinalBuilder 6.&lt;/p&gt;
&lt;p&gt;You can now do things with FinalBuilder 6 and Team Build which are impossible to achieve with any other tool combination, and you can do it all without editing any MSBuild files &lt;span style="text-decoration: underline;"&gt;at all&lt;/span&gt;.&lt;/p&gt;
&lt;p&gt;Need MbUnit test statistics in your Team Build Quality Report? &lt;em&gt;Do it with FinalBuilder.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Need to deploy build results via FTP? &lt;em&gt;Do it with FinalBuilder.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Need to build legacy Visual Studio 2003/Delphi/C++ Builder/VB 6 projects with Team Build, and see compiler metrics in the Team Build Report? &lt;em&gt;Do it with FinalBuilder.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Need smart version information management (including auto-incrementing version numbers across projects) without having to use custom C# code? &lt;em&gt;Do it with FinalBuilder.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Need to do perform any of the thousands of other built-in operations, with full graphical configuration and structured logging output? &lt;em&gt;Do it with FinalBuilder&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;If you're interested, &lt;a href="http://www.finalbuilder.com/articles.aspx?mid=370&amp;amp;ctl=ArticleView&amp;amp;articleId=29" target="_blank"&gt;check out the new article here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;I also wanted to plug a great (FREE) Screencast creator called &lt;a href="http://www.debugmode.com/wink/" target="_blank"&gt;Wink&lt;/a&gt;, by DebugMode Software. Paul put me onto this and I used it to create the Flash videos in the article. We also have a license to an expensive commercial product, but I don't think I'll ever want to use it again now that I've found Wink.&lt;/p&gt;</description></item><item><title>FinalBuilder 6 Tech Article - .NET custom action API</title><link>http://www.finalbuilder.com/Resources/Blogs/PostId/668/FinalBuilder-6-Tech-Article-NET-custom-action-A.aspx</link><category>FinalBuilder</category><pubDate>Tue, 04 Mar 2008 06:00:00 GMT</pubDate><description>&lt;p&gt;I just posted a new tech article about the &lt;a href="http://www.finalbuilder.com/Default.aspx?tabid=70&amp;amp;mid=370&amp;amp;ctl=ArticleView&amp;amp;articleId=28"&gt;FinalBuilder 6 .NET Custom Action API&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;If you've ever done any custom action development with .NET, then I strongly suggest you check this out. It's a really nifty API and it makes designing FB 6 actions incredibly simple.&lt;/p&gt;
&lt;p&gt;In addition, it is still possible to tweak the API slightly to add functionality before FB 6 goes final - so please let us know if there's anything that you'd like to see added.&lt;/p&gt;</description></item><item><title>"The Bus Factor", Software Development practices, and FinalBuilder</title><link>http://www.finalbuilder.com/Resources/Blogs/PostId/667/The-Bus-Factor-Software-Development-practices-and.aspx</link><category>FinalBuilder</category><pubDate>Wed, 27 Feb 2008 06:00:00 GMT</pubDate><description>&lt;p&gt;(This blog post is shamelessly &lt;span style="text-decoration: line-through;"&gt;ripped off from&lt;/span&gt; based on &lt;a href="http://weblogs.asp.net/rosherove"&gt;Roy Osherove&lt;/a&gt;'s praise of FinalBuilder(&lt;a href="#footnote1"&gt;*&lt;/a&gt;)&lt;a name="footnote1_top"&gt;&lt;/a&gt; during a session at TechEd Barcelona last year.)&lt;/p&gt;
&lt;p &gt;
&lt;span style="font-size: 18px;"&gt;&lt;em&gt;&lt;em&gt;"&lt;/em&gt;[&lt;em&gt;The Bus Factor]&lt;/em&gt; means if the developer who wrote [the project] is hit by a bus, you're screwed."&lt;/em&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;- &lt;a href="http://www.hanselman.com/blog/StrippingOutEmptyXmlElementsInAPerformantWayAndTheBusFactor.aspx"&gt;Scott Hanselman&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;It's common to talk about the Bus Factor of a software project or a piece of code. Specifically, the Bus Factor is the number of people on your team who need to be "hit by a bus" (or change jobs, or change projects, or move away, or retire, or get sat on by an elephant) before the project is in trouble. The hallmark of a bad Bus Factor is having specialised, hard to access, knowledge which is only understood by one or two people on your team.&lt;/p&gt;
&lt;p&gt;FinalBuilder encourages a good Bus Factor for builds.&lt;/p&gt;
&lt;p&gt;To help demonstrate this, here's the Nant build process for one of my favourite .NET Open Source tools, &lt;a href="http://www.nunit.org"&gt;NUnit&lt;/a&gt;:&lt;/p&gt;
&lt;p&gt;(Start scrolling now...)&lt;/p&gt;
&lt;p&gt;&lt;a href="/blogimages/busfactor/NantBuild_1.png"&gt; &lt;img alt="" src="/blogimages/busfactor/Thumbs/NantBuild_1.png" /&gt; &lt;/a&gt; &lt;a href="/blogimages/busfactor/NantBuild_2.png"&gt; &lt;img alt="" src="/blogimages/busfactor/Thumbs/NantBuild_2.png" /&gt; &lt;/a&gt; &lt;a href="/blogimages/busfactor/NantBuild_3.png"&gt; &lt;img alt="" src="/blogimages/busfactor/Thumbs/NantBuild_3.png" /&gt; &lt;/a&gt; &lt;a href="/blogimages/busfactor/NantBuild_4.png"&gt; &lt;img alt="" src="/blogimages/busfactor/Thumbs/NantBuild_4.png" /&gt; &lt;/a&gt; &lt;a href="/blogimages/busfactor/NantBuild_5.png"&gt; &lt;img alt="" src="/blogimages/busfactor/Thumbs/NantBuild_5.png" /&gt; &lt;/a&gt; &lt;a href="/blogimages/busfactor/NantBuild_6.png"&gt; &lt;img alt="" src="/blogimages/busfactor/Thumbs/NantBuild_6.png" /&gt; &lt;/a&gt; &lt;a href="/blogimages/busfactor/NantBuild_7.png"&gt; &lt;img alt="" src="/blogimages/busfactor/Thumbs/NantBuild_7.png" /&gt; &lt;/a&gt; &lt;a href="/blogimages/busfactor/NantBuild_8.png"&gt; &lt;img alt="" src="/blogimages/busfactor/Thumbs/NantBuild_8.png" /&gt; &lt;/a&gt; &lt;a href="/blogimages/busfactor/NantBuild_9.png"&gt; &lt;img alt="" src="/blogimages/busfactor/Thumbs/NantBuild_9.png" /&gt; &lt;/a&gt; &lt;a href="/blogimages/busfactor/NantBuild_10.png"&gt; &lt;img alt="" src="/blogimages/busfactor/Thumbs/NantBuild_10.png" /&gt; &lt;/a&gt; &lt;a href="/blogimages/busfactor/NantBuild_11.png"&gt; &lt;img alt="" src="/blogimages/busfactor/Thumbs/NantBuild_11.png" /&gt; &lt;/a&gt; &lt;a href="/blogimages/busfactor/NantBuild_12.png"&gt; &lt;img alt="" src="/blogimages/busfactor/Thumbs/NantBuild_12.png" /&gt; &lt;/a&gt; &lt;a href="/blogimages/busfactor/NantBuild_13.png"&gt; &lt;img alt="" src="/blogimages/busfactor/Thumbs/NantBuild_13.png" /&gt; &lt;/a&gt; &lt;a href="/blogimages/busfactor/NantBuild_14.png"&gt; &lt;img alt="" src="/blogimages/busfactor/Thumbs/NantBuild_14.png" /&gt; &lt;/a&gt; &lt;a href="/blogimages/busfactor/NantBuild_15.png"&gt; &lt;img alt="" src="/blogimages/busfactor/Thumbs/NantBuild_15.png" /&gt; &lt;/a&gt; &lt;a href="/blogimages/busfactor/NantBuild_16.png"&gt; &lt;img alt="" src="/blogimages/busfactor/Thumbs/NantBuild_16.png" /&gt; &lt;/a&gt; &lt;a href="/blogimages/busfactor/NantBuild_17.png"&gt; &lt;img alt="" src="/blogimages/busfactor/Thumbs/NantBuild_17.png" /&gt; &lt;/a&gt; &lt;a href="/blogimages/busfactor/NantBuild_18.png"&gt; &lt;img alt="" src="/blogimages/busfactor/Thumbs/NantBuild_18.png" /&gt; &lt;/a&gt; &lt;a href="/blogimages/busfactor/NantBuild_19.png"&gt; &lt;img alt="" src="/blogimages/busfactor/Thumbs/NantBuild_19.png" /&gt; &lt;/a&gt; &lt;a href="/blogimages/busfactor/NantBuild_20.png"&gt; &lt;img alt="" src="/blogimages/busfactor/Thumbs/NantBuild_20.png" /&gt; &lt;/a&gt; &lt;a href="/blogimages/busfactor/NantBuild_21.png"&gt; &lt;img alt="" src="/blogimages/busfactor/Thumbs/NantBuild_21.png" /&gt; &lt;/a&gt; &lt;a href="/blogimages/busfactor/NantBuild_22.png"&gt; &lt;img alt="" src="/blogimages/busfactor/Thumbs/NantBuild_22.png" /&gt; &lt;/a&gt; &lt;a href="/blogimages/busfactor/NantBuild_23.png"&gt; &lt;img alt="" src="/blogimages/busfactor/Thumbs/NantBuild_23.png" /&gt; &lt;/a&gt; &lt;a href="/blogimages/busfactor/NantBuild_24.png"&gt; &lt;img alt="" src="/blogimages/busfactor/Thumbs/NantBuild_24.png" /&gt; &lt;/a&gt; &lt;a href="/blogimages/busfactor/NantBuild_25.png"&gt; &lt;img alt="" src="/blogimages/busfactor/Thumbs/NantBuild_25.png" /&gt; &lt;/a&gt; &lt;a href="/blogimages/busfactor/NantBuild_26.png"&gt; &lt;img alt="" src="/blogimages/busfactor/Thumbs/NantBuild_26.png" /&gt; &lt;/a&gt; &lt;a href="/blogimages/busfactor/NantBuild_27.png"&gt; &lt;img alt="" src="/blogimages/busfactor/Thumbs/NantBuild_27.png" /&gt; &lt;/a&gt; &lt;a href="/blogimages/busfactor/NantBuild_28.png"&gt; &lt;img alt="" src="/blogimages/busfactor/Thumbs/NantBuild_28.png" /&gt; &lt;/a&gt; &lt;a href="/blogimages/busfactor/NantBuild_29.png"&gt; &lt;img alt="" src="/blogimages/busfactor/Thumbs/NantBuild_29.png" /&gt; &lt;/a&gt; &lt;a href="/blogimages/busfactor/NantBuild_30.png"&gt; &lt;img alt="" src="/blogimages/busfactor/Thumbs/NantBuild_30.png" /&gt; &lt;/a&gt; &lt;a href="/blogimages/busfactor/NantBuild_31.png"&gt; &lt;img alt="" src="/blogimages/busfactor/Thumbs/NantBuild_31.png" /&gt; &lt;/a&gt; &lt;a href="/blogimages/busfactor/NantBuild_32.png"&gt; &lt;img alt="" src="/blogimages/busfactor/Thumbs/NantBuild_32.png" /&gt; &lt;/a&gt; &lt;a href="/blogimages/busfactor/NantBuild_33.png"&gt; &lt;img alt="" src="/blogimages/busfactor/Thumbs/NantBuild_33.png" /&gt; &lt;/a&gt; &lt;a href="/blogimages/busfactor/NantBuild_34.png"&gt; &lt;img alt="" src="/blogimages/busfactor/Thumbs/NantBuild_34.png" /&gt; &lt;/a&gt; &lt;a href="/blogimages/busfactor/NantBuild_35.png"&gt; &lt;img alt="" src="/blogimages/busfactor/Thumbs/NantBuild_35.png" /&gt; &lt;/a&gt; &lt;a href="/blogimages/busfactor/NantBuild_36.png"&gt; &lt;img alt="" src="/blogimages/busfactor/Thumbs/NantBuild_36.png" /&gt; &lt;/a&gt; &lt;a href="/blogimages/busfactor/NantBuild_37.png"&gt; &lt;img alt="" src="/blogimages/busfactor/Thumbs/NantBuild_37.png" /&gt; &lt;/a&gt; &lt;a href="/blogimages/busfactor/NantBuild_38.png"&gt; &lt;img alt="" src="/blogimages/busfactor/Thumbs/NantBuild_38.png" /&gt; &lt;/a&gt; &lt;a href="/blogimages/busfactor/NantBuild_39.png"&gt; &lt;img alt="" src="/blogimages/busfactor/Thumbs/NantBuild_39.png" /&gt; &lt;/a&gt; &lt;a href="/blogimages/busfactor/NantBuild_40.png"&gt; &lt;img alt="" src="/blogimages/busfactor/Thumbs/NantBuild_40.png" /&gt; &lt;/a&gt; &lt;a href="/blogimages/busfactor/NantBuild_41.png"&gt; &lt;img alt="" src="/blogimages/busfactor/Thumbs/NantBuild_41.png" /&gt; &lt;/a&gt; &lt;a href="/blogimages/busfactor/NantBuild_42.png"&gt; &lt;img alt="" src="/blogimages/busfactor/Thumbs/NantBuild_42.png" /&gt; &lt;/a&gt; &lt;a href="/blogimages/busfactor/NantBuild_43.png"&gt; &lt;img alt="" src="/blogimages/busfactor/Thumbs/NantBuild_43.png" /&gt; &lt;/a&gt;&lt;/p&gt;
&lt;p&gt;(&lt;a href="#footnote2"&gt;**&lt;/a&gt;)&lt;a name="footnote2_top"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The build process is 2,688 lines of XML, spread amongst 33 XML files. I combined them all into a PDF to create the images shown above. NUnit uses NAnt, but if you're using MSBuild then your build process will look very similar.&lt;/p&gt;
&lt;p&gt;Comparatively speaking, this a simple build process. The entire NUnit codebase is only around 70 thousand lines of C# code. The build above doesn't do anything particularly complex. Imagine how much worse this gets if either the codebase, or the level of functionality, needs to grow.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Would you want to be a new developer in charge of working on that build process?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;For comparison sake, I recreated most of the NUnit build functionality in FinalBuilder (this is based on a rolling demo that we used at TechEd Barcelona.)&lt;/p&gt;
&lt;p&gt;&lt;img src="/blogimages/busfactor/FinalBuilder_1.png" alt="Main Action List" /&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;img src="/blogimages/busfactor/FinalBuilder_2.png" alt="PreBuild Action List" /&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;img src="/blogimages/busfactor/FinalBuilder_3.png" alt="Build and Test" /&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;img src="/blogimages/busfactor/FinalBuilder_4.png" alt="PostBuild" /&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;img src="/blogimages/busfactor/FinalBuilder_5.png" alt="Clean" /&gt;&lt;/p&gt;
&lt;p&gt;The FinalBuilder project doesn't do absolutely everything that the NAnt script does, but it could be extended to fill in the gaps without changing the appearance drastically from what you see here. The FinalBuilder project also does do some things that the NAnt project does not do - namely version control integration and FTP deployment.&lt;/p&gt;
&lt;p&gt;Ask yourself: &lt;strong&gt;Which type of build process would I like to see deployed in my organization?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Nitpicker's Corner&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;This isn't an entirely fair comparison, because lots of the details about &lt;em&gt;how&lt;/em&gt; the FinalBuilder project works are hidden away under the GUI abstraction. That's my the point, though: In FinalBuilder the project details aren't all in your face, but they're easy to find and understand if the person who wrote the build process happens to get hit by a bus.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&amp;nbsp;Footnotes:&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;a name="footnote1"&gt;&lt;/a&gt;(*) For the record, we didn't ask Roy to praise FinalBuilder, and we definitely didn't pay him to do so. He said it all off his own bat. I hope he doesn't mind me quoting him. (&lt;a href="#footnote1_top"&gt;back&lt;/a&gt;)&lt;/p&gt;
&lt;p&gt;&lt;a name="footnote2"&gt;&lt;/a&gt;(**) I don't mean to pick on NUnit here. Naturally, OSS development involves different factors which come into play when choosing tools. That said, we'd be happy to offer the NUnit project a free license (or two) of FinalBuilder for use with internal build and configuration management. (&lt;a href="#footnote2_top"&gt;back&lt;/a&gt;)&lt;/p&gt;</description></item><item><title>Safely Using Relative Paths in Actions</title><link>http://www.finalbuilder.com/Resources/Blogs/PostId/666/Safely-Using-Relative-Paths-in-Actions.aspx</link><category>Automise,FinalBuilder</category><pubDate>Tue, 26 Feb 2008 06:00:00 GMT</pubDate><description>&lt;p&gt;Using relative paths in a project is a good idea - they make a project more maintainable, readable and portable.&lt;/p&gt;
&lt;p&gt;However, lately I've seen quite a few sample FinalBuilder projects where people are using this kind of relative path in their actions:&lt;/p&gt;
&lt;p&gt;
&lt;/p&gt;
&lt;table width="200" cellspacing="1" cellpadding="1" border="1"&gt;
    &lt;tbody&gt;
        &lt;tr&gt;
            &lt;td&gt;MySolutionFile.sln&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
            &lt;td&gt;.\MyProject\Installer\Project.iss&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
            &lt;td&gt;..\..\MyOtherProject\MyProject.dproj&lt;/td&gt;
        &lt;/tr&gt;
    &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;The idea is that if the file is located relative to the project file path, the relative path will resolve to the right directory.&lt;/p&gt;
&lt;p&gt;Great idea, right? Unfortunately, no.&lt;/p&gt;
&lt;p&gt;These relative paths rely on the current Windows working directory for the process. Unfortunately, FinalBuilder and Automise only have limited control over this property. Various API calls (made by actions, scripts or the IDE) might change this directory unexpectedly.&lt;/p&gt;
&lt;p&gt;The safe way to use relative paths in a FinalBuilder or Automise project is to use the variable &lt;strong&gt;%FBPROJECTDIR%&lt;/strong&gt; (called &lt;strong&gt;%PROJECTDIR%&lt;/strong&gt; in Automise.) This variable evaluates to the directory which contains the current project file.&lt;/p&gt;
&lt;p&gt;
&lt;/p&gt;
&lt;table width="200" cellspacing="1" cellpadding="1" border="1"&gt;
    &lt;tbody&gt;
        &lt;tr&gt;
            &lt;td&gt;&lt;strong&gt;Unsafe&lt;/strong&gt;&lt;/td&gt;
            &lt;td&gt;&lt;strong&gt;Safe&lt;/strong&gt;&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
            &lt;td&gt;MySolution.sln&lt;/td&gt;
            &lt;td&gt;%FBPROJECTDIR%\MySolution.sln&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
            &lt;td&gt;.\MyProject\&lt;/td&gt;
            &lt;td&gt;%FBPROJECTDIR%\MyProject\Installer\Project.iss&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
            &lt;td&gt;..\..\MyOtherProject\MyProject.dproj&lt;/td&gt;
            &lt;td&gt;%FBPROJECTDIR%\..\..\MyOtherProject\MyProject.dproj&lt;/td&gt;
        &lt;/tr&gt;
    &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;We recommend defining new project variables to prevent these paths from becoming too long and unwieldy, and to make your project easier to read.&lt;/p&gt;
&lt;p&gt;For instance, you could define a project variable called &lt;em&gt;InstallerPath&lt;/em&gt; and set it to &lt;em&gt;%FBPROJECTDIR%\MyProject\Installer&lt;/em&gt;. Turn on the "Macro" option for the &lt;em&gt;InstallerPath&lt;/em&gt; variable to make sure variable references are expanded each time the variable is read.&lt;/p&gt;
&lt;p&gt;&lt;img src="/blogimages/FBPROJECTDIR-AddVariableMacro.png" alt="Add Macro Variable " /&gt;&lt;/p&gt;</description></item><item><title>XML Actions and the "XPath returned no node" error.</title><link>http://www.finalbuilder.com/Resources/Blogs/PostId/665/XML-Actions-and-the-XPath-returned-no-node-error.aspx</link><category>Automise,FinalBuilder</category><pubDate>Mon, 25 Feb 2008 06:00:00 GMT</pubDate><description>&lt;p&gt;(It's been a while since I blogged about anything, so I thought I'd write about this while my coffee kicks in on a Monday morning.)&lt;/p&gt;
&lt;p&gt;An issue which comes up quite often is people seeing this error when they try to use XML actions in FinalBuilder or Automise:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;XPath returned no node : /Project/Import&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;The reason is because of the way MSXML deals with document namespaces.&amp;nbsp; If your XML file uses XML namespaces (and most do), then you need to tweak the action slightly.&lt;/p&gt;
&lt;p&gt;I'm not going to go into XML Namespaces in detail. There are &lt;a href="http://www.w3schools.com/xml/xml_namespaces.asp"&gt;better places to learn about them&lt;/a&gt;. I'll just show you an example:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Example&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Say you have a Visual Studio 2005 .csproj file (which is really just an XML file wearing a funny hat.) You want to iterate over all of the imported project names with an XML Node Iterator action. If you try to use the XPath &lt;em&gt;/Project/Import&lt;/em&gt;, then you'll see the error I showed above.&lt;/p&gt;
&lt;p&gt;Here's the first line of the .csproj file:&lt;/p&gt;
&lt;xmp&gt;&amp;lt;Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"&amp;gt;&lt;/xmp&gt;
&lt;p&gt;This means the document has a &lt;strong&gt;default XML Namespace&lt;/strong&gt;, which is "&lt;em&gt;http://schemas.microsoft.com/blahblahblah&lt;/em&gt;". This is why MSXML can't follow the XPath properly.&lt;/p&gt;
&lt;p&gt;To fix this, open the XML action and navigate to the "MSXML Parser" page.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;img src="/blogimages/DefaultXMLNamespace.png" alt="MSXML Parser Dialog" /&gt;&lt;/p&gt;
&lt;p&gt;Turn on the "Automatically use namespace prefixes..." checkbox, and type a letter in the field for the default Namespace. I used "x" in the screenshot shown above.&lt;/p&gt;
&lt;p&gt;Now change your XPath from &lt;em&gt;/Project/Import&lt;/em&gt; to:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;/x:Project/x:Import&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;It works! Namespace prefix "x" now refers to the default namespace in the document.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Pedantic Details&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
    &lt;li&gt;There is a way to specify the namespace URI as part of the XPath, without using this prefix feature, but the resulting XPaths are enormous and hard for humans to read.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul&gt;
    &lt;li&gt;If you have namespace prefixes defined as attributes in the document root node, ie &lt;em&gt;s:xmlns="http://www.myfunkyurl.com/namespace"&lt;/em&gt;, then turning on this option will let you use the prefixes in your XPath.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul&gt;
    &lt;li&gt;This is the best solution we've come up with so far. We're planning to revisit this in future and (hopefully) make it all automatic without any manual configuration or custom prefixes.&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>MSBuild Wish List vs FinalBuilder Feature Set</title><link>http://www.finalbuilder.com/Resources/Blogs/PostId/664/MSBuild-Wish-List-vs-FinalBuilder-Feature-Set.aspx</link><category>FinalBuilder</category><pubDate>Fri, 07 Dec 2007 03:47:46 GMT</pubDate><description>&lt;p&gt;The MSBuild Team recently posted a "&lt;a href="http://blogs.msdn.com/msbuild/archive/2007/11/17/how-would-you-spend-100-on-msbuild.aspx"&gt;wish list&lt;/a&gt;" of potential new MSBuild features, and encouraged people to vote on which ones they would like to see in future versions. &lt;a href="http://blogs.msdn.com/msbuild/archive/2007/11/30/response-to-the-feature-poll.aspx"&gt;The results&lt;/a&gt; came out last week.&lt;/p&gt;
&lt;p&gt;We have a lot of respect for MSBuild here at VSoft Technologies. We're committed to making our own MSBuild support top-notch so you can easily interoperate between FinalBuilder and MSBuild projects. However, I wouldn't recommend MSBuild for end-to-end build automation.&lt;/p&gt;
&lt;p&gt;I couldn't help but compare the top ten most popular MSBuild feature requests with existing FinalBuilder features. &lt;span style="font-family: arial, sans-serif; font-size: 10pt;"&gt;  &lt;/span&gt;&lt;/p&gt;
&lt;h4&gt;&lt;span style="font-weight: bold;"&gt;1)&amp;nbsp; Debugger&lt;br /&gt;
&lt;/span&gt;&lt;/h4&gt;
&lt;p&gt;FinalBuilder gives you a full graphical debugging environment - breakpoints, stepping, watches, pause and resume.&lt;/p&gt;
&lt;p&gt;You also get a structured log which quickly allows you to move between your project's structure and it's output. No need to scan text log files for line numbers and target names.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;2)&lt;/strong&gt; and &lt;strong&gt;3)&lt;/strong&gt; These both relate to converting existing non-MSBuild-friendly formats to MSBuild. This problem is more or less bypassed if you use FinalBuilder, because the built-in action types give you "first class" access to building these project types.&lt;/p&gt;
&lt;p &gt;
&lt;strong&gt;4) Visualization&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;This is another feature that FinalBuilder gives you "out of the box" - FinalBuilder projects are represented as structured trees, and refactoring is often as simple as drag-and-drop.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;5) Native Code / VC Support&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;FinalBuilder has built-in support for Visual C++, at the same level of integration as other tools.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;6) Distributed Builds&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;FinalBuilder doesn't do this either. Yet.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;7) Extensible reuseable inline tasks&lt;br /&gt;
&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Every single action in FinalBuilder has extensibility built in via VBScript, JavaScript, and soon PowerShell. (Ssh! Don't tell anyone I told you!)&amp;nbsp; If that's not enough, with ActionStudio you can whip up a custom action type in minutes, using one of these scripting languages or .NET.&lt;/p&gt;
&lt;p&gt;For further extensibility, resuseable action lists can be easily created and called from different parts of your project.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;8) Multiprocessor Peformance&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Async Action Groups let you automatically schedule parts of your build to run in parallel with others, allowing you to take advantage of multiprocessor architectures.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;9) Extensible Functions&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;See No. 7. The inclusion of scripting throughout a FinalBuilder project makes it easy to extend specific fields.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;10) (Editing UI)&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;This is FinalBuilder's core feature. The FinalBuilder IDE gives you a clear graphical layout of your build process, and combined with debugging and structured logging you have a quick and easy way to move between project structure and project output.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;</description></item><item><title>"I have Microsoft Team System, why do I need FinalBuilder?"</title><link>http://www.finalbuilder.com/Resources/Blogs/PostId/663/I-have-Microsoft-Team-System-why-do-I-need-FinalB.aspx</link><category>FinalBuilder,TFS</category><pubDate>Wed, 07 Nov 2007 14:19:44 GMT</pubDate><description>&lt;p&gt;I'm writing this entry from a delegate work area at TechEd Barcelona. We've been talking to a lot of people over the past two days about FinalBuilder.&lt;/p&gt;
&lt;p&gt;Many people have said "Oh, we have Team System. We already have automated builds." The surprising thing is how many people don't realise what they're missing out on, or that FinalBuilder can integrate directly with Team System.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;With Team System you can do this in your build:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
    &lt;li&gt;Get a fresh copy of your project's source&lt;/li&gt;
    &lt;li&gt;Build one or more Visual Studio 2005 solutions&lt;/li&gt;
    &lt;li&gt;Run Visual Studio tests &amp;amp; Visual Studio code coverage analysis&lt;/li&gt;
    &lt;li&gt;Deploy built applications to a network share&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;... &lt;strong&gt;that's about it&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Not that this is a bad thing - sometimes all you need to do is to build a solution, and you're done. It's still an automated build, and it's a world better than &lt;a href="http://www.codinghorror.com/blog/archives/000988.html"&gt;F5 as a build process&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;However, &lt;strong&gt;with FinalBuilder you can easily extend Team Build to:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
    &lt;li&gt;Change the build process without editing XML&lt;/li&gt;
    &lt;li&gt;Automatically update and increment version information&lt;/li&gt;
    &lt;li&gt;Build solutions with any version of Visual Studio or MSBuild&lt;/li&gt;
    &lt;li&gt;Create, edit or remove Work Items based on build outcomes&lt;/li&gt;
    &lt;li&gt;Deploy to multiple locations, or via FTP&lt;/li&gt;
    &lt;li&gt;Build third party projects&lt;/li&gt;
    &lt;li&gt;Build installers&lt;/li&gt;
    &lt;li&gt;Run tests using different test frameworks&lt;/li&gt;
    &lt;li&gt;Build multiple versions or editions of the same product&lt;/li&gt;
    &lt;li&gt;Build legacy code (possibly using different tools)&lt;/li&gt;
    &lt;li&gt;Retrieve source code from legacy source repositories&lt;/li&gt;
    &lt;li&gt;Generate structured build logs, with the ability to instantly jump to any points of failure.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;a href="http://finalbuilder.com/articles.aspx?mid=370&amp;amp;ctl=ArticleView&amp;amp;articleId=20"&gt;FinalBuilder slots directly into Team Build as a build engine, in place of (or beside) MSBuild&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;At TechEd, many people have recognised that they face one or more of these scenarios. A few have no other build requirements, but a lot of people have said "Oh, we've been doing that manually" or "Yes, we've been doing this with MSBuild but it's hard and it keeps breaking."&lt;/p&gt;
&lt;p&gt;These are the cases where FinalBuilder can help create a true end-to-end build and release system, one which saves time and money and helps safeguard build quality and avoid last-minute surprises.&lt;/p&gt;
&lt;p&gt;... and no more XML files!&lt;/p&gt;</description></item><item><title>Blogging from TechEd in Barcelona</title><link>http://www.finalbuilder.com/Resources/Blogs/PostId/662/Blogging-from-TechEd-in-Barcelona.aspx</link><category /><pubDate>Mon, 05 Nov 2007 06:00:00 GMT</pubDate><description>&lt;p&gt;After a great two weeks holidaying in Germany and Spain, I'm back at work as we set up our booth at TechEd Barcelona. I'm looking forward to seeing some demos of new Microsoft technologies.&lt;/p&gt;
&lt;p&gt;We also have some exciting things to show in our booth here - a FinalBuilder build integrated with Team Foundation Server, some sneak peeks of the next FinalBuilder version, and some nifty Automise demos. Come by the Exhibitor Hall if you get a chance.&lt;/p&gt;</description></item><item><title>Automising the Calculator</title><link>http://www.finalbuilder.com/Resources/Blogs/PostId/657/Automising-the-Calculator.aspx</link><category>Automise</category><pubDate>Fri, 10 Aug 2007 01:06:55 GMT</pubDate><description>&lt;div style="text-align: left;"&gt;&lt;br /&gt;
&lt;object width="640" height="480" align="middle" data="/Portals/0/LinkedFiles/FlowPlayerWhite.swf" type="application/x-shockwave-flash" id="FlowPlayer"&gt;
&lt;param="" value="sameDomain" name="allowScriptAccess"&gt;
&lt;param="" value="/Portals/0/LinkedFiles/FlowPlayer.swf" name="movie"&gt;
&lt;param="" value="high" name="quality"&gt;
&lt;param="" value="noScale" name="scale"&gt;
&lt;param="" value="transparent" name="wmode"&gt;
&lt;/param=""&gt;
&lt;/param=""&gt;
&lt;/param=""&gt;
&lt;/param=""&gt;
&lt;/param=""&gt;
&lt;/object&gt;&lt;br /&gt;
&lt;/div&gt;
&lt;br /&gt;
&lt;p&gt;NB: The project includes delay actions so you can see what's going on. Disable them, and it will run even faster!&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;
&lt;/p&gt;
&lt;p&gt;Want to try it yourself? Download the &lt;a href="/LinkClick.aspx?link=125&amp;amp;tabid=70"&gt;Automise 2 Release Candidate&lt;/a&gt;, and the &lt;a href="http://www.finalbuilder.com/Portals/0/LinkedFiles/Calculator Demo.atz2"&gt;Calculator Demo project file&lt;/a&gt; (the demo is also included in the Automise 2 installation, under Examples\GUI Automation.&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;
&lt;/p&gt;
&lt;p&gt;This demo may not be particularly useful, but it shows off some of the power of the GUI Automation actions included in Automise 2. The demo project was created and tested in a matter of minutes. I've written a &lt;a href="http://www.finalbuilder.com/Resources/Articles/ID/24/Automating-GUI-Applications-with-Automise-2.aspx"&gt;longer article on the subject&lt;/a&gt;, if you are interested in reading some more.&lt;/p&gt;</description></item><item><title>CruiseControl.NET Plugin Released</title><link>http://www.finalbuilder.com/Resources/Blogs/PostId/655/CruiseControlNET-Plugin-Released.aspx</link><category /><pubDate>Thu, 19 Jul 2007 05:00:00 GMT</pubDate><description>&lt;p&gt;EDIT: &lt;a href="http://ccnet.thoughtworks.com/"&gt;CruiseControl.NET version 1.3&lt;/a&gt; now ships with an integrated &lt;a href="http://confluence.public.thoughtworks.org/display/CCNET/FinalBuilder+Task"&gt;FinalBuilder Task&lt;/a&gt;. No more need for a plugin.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;A few people have been enjoying this for a while, but you can now download an installer for the FinalBuilder CruiseControl.NET plugin. The plugin makes FinalBuilder available as a CruiseControl.NET build engine for continuous integration. The plugin is free, and works with both&amp;nbsp;FinalBuilder 3 and 4 (although FB 3 users will need the Professional Edition.)&lt;/p&gt;
&lt;p&gt;The current version of the plugin is for &lt;a href="http://ccnet.thoughtworks.com/"&gt;CruiseControl.NET 1.0&lt;/a&gt;, and we will make sure it&amp;nbsp;keeps up to date&amp;nbsp;with the current stable release.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;</description></item><item><title>Runtime Assembly Reference Loading and the CLR</title><link>http://www.finalbuilder.com/Resources/Blogs/PostId/660/Runtime-Assembly-Reference-Loading-and-the-CLR.aspx</link><category>.NET</category><pubDate>Fri, 06 Jul 2007 05:00:00 GMT</pubDate><description>&lt;p&gt;Following on from my &lt;a href="http://www.finalbuilder.com/blogs.aspx?EntryID=239"&gt;earlier post&lt;/a&gt; about Assembly resolution and CLR versions, I have an observation to share about the .NET Just-In-Time compiler and the resolution of Assembly references. It's a fairly simple observation, but it came as a surprise to me.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;DISCLAIMER: This is just an observation. I can't find any real concrete specification of the behaviour I'm describing. My supporting documents are &lt;a href="http://research.microsoft.com/~zorn/mre04/PreJit%20Talk.ppt"&gt;this PowerPoint presentation&lt;/a&gt;, and &lt;a href="http://pubs.doc.ic.ac.uk/FlexibleLinking/FlexibleLinking.pdf"&gt;this doctoral thesis&lt;/a&gt;.&amp;nbsp; If you have better references, or consider this either blindingly obvious or blindingly wrong, please post in the comments.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;I used to think that if "Assembly A" references another assembly, "Assembly B", then Assembly B is loaded (or at least validated) when Assembly A is loaded. If Assembly B is missing, Assembly A won't run. Am I right?&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;It appears I am not right. The rule is that Assembly B will not normally be resolved (ie checked for existence and loaded) until the JIT compiler encounters some code which references a type belonging to that assembly. You could delete Assembly B entirely and Assembly A would work perfectly, providing it didn't touch Assembly B's types in any of the codepaths which you take.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;I put together a simple pair of C# projects which demonstrate this behaviour. You can download them &lt;a href="http://www.finalbuilder.com/blogimages/angus/AssemblyResolution/Assembly%20Resolution%20Example.zip"&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;The projects build two assemblies, ResolutionTest.exe and MissingAssembly.dll (such creative names!)&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;img src="/blogimages/angus/AssemblyResolution/folderBefore.png" alt="One .DLL and One .EXE File" /&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;MissingAssembly contains one class, MissingClass. ResolutionTest contains a static Program class and another class, MainClass. Here is the code for MainClass:&lt;/p&gt;
&lt;p&gt;&lt;img src="/blogimages/angus/AssemblyResolution/mainClass.png" alt="MainClass Source" /&gt;&lt;/p&gt;
&lt;p&gt;(This is the executive summary version. The actual source has some other attributes and comments about inlining. I'll get to that in a minute.)&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Here's what happens when it runs:&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;img src="/blogimages/angus/AssemblyResolution/appBefore.png" alt="Normal Execution" /&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;No great surprises. A MainClass object is instantiated. The constructor calls the SubMethod() method, which then creates a new object of type MissingClass from the MissingAssembly.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style="text-align: left;"&gt;Now, suppose we delete MissingAssembly:&lt;/p&gt;
&lt;p style="text-align: left;"&gt;&lt;img align="left" src="/blogimages/angus/AssemblyResolution/folderAfter.png" alt="Just an EXE, no DLL" style="float: left;" /&gt;&lt;/p&gt;
&lt;p style="text-align: left;"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;img src="/blogimages/angus/AssemblyResolution/appAfter.png" alt="Uh-oh! An exception!" /&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;An exception is raised because it can't find the MissingAssembly object. However, the MainClass() constructor still executes. The FileNotFoundException occurs when the call to SubMethod() is made. The JITter has examined SubMethod() and said "I need a MissingClass which is held in assembly MissingAssembly. I'd better go find that...", and then failed to find it.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;
&lt;/strong&gt;&lt;/p&gt;
&lt;h3&gt;&lt;strong&gt;Why is this worth knowing?&lt;/strong&gt;&lt;/h3&gt;
&lt;strong&gt;
&lt;/strong&gt;
&lt;p&gt;Because (I think) it means that you can "cheat" when binding assemblies. Previously I'd used late binding&amp;nbsp; via Reflection (&lt;a href="http://www.c-sharpcorner.com/UploadFile/samhaidar/LateBindingWithReflection09122005053810AM/LateBindingWithReflection.aspx"&gt;like this&lt;/a&gt;) when I didn't know if something might or might not be installed on the end user's machine. As far as I can tell, this approach is not wholly necessary - If the "third party" type references are all encapsulated nicely away from the "main" code, it should be possible to just use exception handling to react if the types aren't available at JIT-time.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;It's also worth knowing because even if you call Assembly.Load() at runtime without any problems, it doesn't mean all the references have resolved. The loaded assembly could still break when you go to use it.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3&gt;&lt;strong&gt;Some things to remember&lt;/strong&gt;:&lt;/h3&gt;
&lt;ul style="list-style-type: disc;"&gt;
    &lt;li&gt;This isn't something that you can should use every day. You can dig yourself a big hole of shoddy design by doing this. In my case, I just needed a clean way to disable some functionality and fail cleanly when optional assemblies weren't available.&lt;/li&gt;
    &lt;li style="padding-top: 5px; padding-right: 5px; padding-bottom: 5px; padding-left: 5px;"&gt;The assemblies still have to be available when the source is compiled to IL. You can't compile IL which references types or assemblies that do not exist.&lt;/li&gt;
    &lt;li style="padding-top: 5px; padding-right: 5px; padding-bottom: 5px; padding-left: 5px;"&gt;This knowledge can help you &lt;a href="http://msdn2.microsoft.com/en-us/library/ms998547.aspx#scalenetchapt05_topic33"&gt;optimize your code&lt;/a&gt;, by controlling when extra loading and JITting is performed.&lt;/li&gt;
    &lt;li style="padding-top: 5px; padding-right: 5px; padding-bottom: 5px; padding-left: 5px;"&gt;There is a chance that the JITter will &lt;a href="http://blogs.msdn.com/ericgu/archive/2004/01/29/64717.aspx"&gt;inline lightweight method calls&lt;/a&gt;. If MainClass.SubMethod() is inlined into the constructor, then it's possible that the constructor will fail. I originally tried to avoid this by attaching &lt;a href="http://msdn2.microsoft.com/en-us/library/system.runtime.compilerservices.methodimploptions.aspx"&gt;MethodImplOptions.NoInlining&lt;/a&gt; to SubMethod(). However, in the end I couldn't make it inline the code under any circumstances. It's possible that the JITter notices the unloaded type inside the method, and decides not to inline for that reason.&lt;/li&gt;
    &lt;li style="padding-top: 5px; padding-right: 5px; padding-bottom: 5px; padding-left: 5px;"&gt;It's a bit of a hack, but you could dynamically link to one of several available assemblies at runtime, by going through a series of alternative wrapper classes (each referencing different assemblies) and finding the one which loads successfully. If all of the wrappers implemented a common interface, you could then use the components interchangeably with acceptable performance. A more generalised CLR-supported model of this is described in the doctoral thesis I linked to above (he demonstrates dynamically choosing an alternative to Windows.Forms for GUI display when running &lt;a href="http://research.microsoft.com/programs/europe/rotor/"&gt;Rotor&lt;/a&gt; on OS X or Linux.)&lt;/li&gt;
    &lt;li style="padding-top: 5px; padding-right: 5px; padding-bottom: 5px; padding-left: 5px;"&gt;This probably doesn't work if you've used ngen.exe, for obvious reasons.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Happy coding!&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;</description></item><item><title>Automise, FinalBuilder and XML Formatted Data</title><link>http://www.finalbuilder.com/Resources/Blogs/PostId/661/Automise-FinalBuilder-and-XML-Formatted-Data.aspx</link><category>Automise,FinalBuilder</category><pubDate>Thu, 05 Jul 2007 22:36:17 GMT</pubDate><description>&lt;p&gt;Now and again people comment that they think FinalBuilder or Automise uses proprietary binary formats. I sympathise entirely. Binary formats are a pain to work with in version control, and a format like XML can be great when you need to make a sweeping change or tweak something. (If the people who make our help authoring tool are reading this post, please take note!)&lt;/p&gt;
&lt;br /&gt;
&lt;p&gt;The good news is that all of FinalBuilder and Automise's data is available via XML or raw text, you just need to know how to look for it!&lt;/p&gt;
&lt;br /&gt;
&lt;h2&gt;The project files are XML&lt;/h2&gt;
&lt;p&gt;Both Automise and FinalBuilder save their project files as XML. If you save in the .FBP5 / .ATP2 "uncompressed" project format, then the project file is actually just an XML document. The XML isn't exquisitely formatted for human eyes, but a machine will be able to read it just fine..&lt;/p&gt;
&lt;p&gt;If you save in the .FBZ5 / .ATZ2 "compressed" project format, the project file is compressed using industry-standard zip compression. If you rename the file to .ZIP, and open it in a zip program (like &lt;a href="http://www.7zip.org"&gt;7zip&lt;/a&gt;), then you can view or extract the uncompressed project file inside.&lt;/p&gt;
&lt;p&gt;To choose whether to save "compressed" or "uncompressed" by default, go to Tools -&amp;gt; Options -&amp;gt; General IDE Options -&amp;gt; Design Time Options:&lt;/p&gt;
&lt;p&gt;&lt;img alt="Options Dialog, showing compressed file option" src="/blogimages/angus/xmlformat/options.png" /&gt;&lt;/p&gt;
&lt;br /&gt;
&lt;h2&gt;Project logs can be exported as XML&lt;/h2&gt;
&lt;p&gt;OK, you've got me. Automise and FinalBuilder project log files (.fbl5 and .log2) are a &lt;a href="http://www.nexusdb.com"&gt;proprietary database format&lt;/a&gt;. In the old days, FinalBuilder 1 &amp;amp; 2 used a text formatted log file (or so I'm told.) This led to performance problems with large log files and long running projects. Hence the move to an embedded database engine.&lt;/p&gt;
&lt;p&gt;However, you can still export any project log as XML. To export a single log, go to the History tab, select a log, and click "Export Log to XML" (or HTML, or plain text.) To export the current log automatically as part of a running project, use the Export Log action:&lt;/p&gt;
&lt;p&gt;&lt;img src="/blogimages/angus/xmlformat/exportlog.png" alt="Export Log Properties" /&gt;&lt;/p&gt;
&lt;p&gt;Logs can be exported as text, HTML, or XML. XML formatted logs can be further tweaked via XSLT. It is possible to pass data from FB/AT to the XSL stylesheet, via the use of extra XSLT parameters. If you're interested in writing an XSL transform for the Export Log action, take a look at the "Stylesheets" directory in the FinalBuilder or Automise program directory. It contains the XSL files which are used to do the exports for text, xml and html.&lt;/p&gt;
&lt;h2&gt;The Other Project Files are INI Files&lt;/h2&gt;
&lt;p&gt;Any extra project files (like the FBD data file, or the FBV persistent variables file) are actually INI files which can be viewed in any text editor. Go ahead and try it!&lt;/p&gt;
&lt;br /&gt;
&lt;p&gt;... armed with this knowledge, you should be diffing, merging, checking in, parsing, cutting, pasting and transforming in no time!&lt;/p&gt;</description></item><item><title>Four different flavors of .NET Assemblies and the CLR</title><link>http://www.finalbuilder.com/Resources/Blogs/PostId/659/Four-different-flavors-of-NET-Assemblies-and-the-.aspx</link><category /><pubDate>Tue, 03 Jul 2007 05:00:00 GMT</pubDate><description>&lt;p&gt;(This is a technical post about some of the &amp;quot;gotchas&amp;quot; when coding for .NET on 64- and 32-bit architectures.)&lt;/p&gt;
&lt;h2&gt;The short story:&lt;/h2&gt;
&lt;p&gt;The TeamFoundation client assemblies are x86-only assemblies. They don't work when called from an x64 .NET Application.&lt;/p&gt;
&lt;p&gt;Even though they're in the GAC, you'll get a FileNotFoundException if the CLR tries to load them.&lt;/p&gt;
&lt;h3&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h2&gt;My story:&lt;/h2&gt;
&lt;p&gt;I already knew this, but it took me most of the day to realise that was my problem.&lt;/p&gt;
&lt;h3&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h2&gt;The long story:&lt;/h2&gt;
&lt;p&gt;Microsoft's .NET CLR 2.0 supports three different processor architectures: &lt;a href="http://en.wikipedia.org/wiki/X86_architecture"&gt;x86&lt;/a&gt;, &lt;a href="http://en.wikipedia.org/wiki/X86-64"&gt;x64&lt;/a&gt; and &lt;a href="http://en.wikipedia.org/wiki/Itanium"&gt;IA-64&lt;/a&gt;.&amp;nbsp; This means that there are three different CLR environments. x64 machines can host the x86 CLR alongside the native 64-bit CLR.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Although the CLR executes architecture-agnostic &lt;a href="http://en.wikipedia.org/wiki/Common_Intermediate_Language"&gt;Common Intermediate Language&lt;/a&gt; (aka MSIL) code, any assembly can be marked as only suitable for one of the particular architectures.This is what happens when you choose a &amp;quot;Platform&amp;quot; type for a Visual Studio project. Choosing 'Any CPU' means that the project Assemblies are marked as language-agnostic CIL code.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;It all plays out like this:&lt;/p&gt;
&lt;p&gt;
&lt;table width="496" height="113" cellspacing="1" cellpadding="1" border="1"&gt;
    &lt;tbody&gt;
        &lt;tr&gt;
            &lt;td&gt;&lt;strong&gt;CLR Type&lt;/strong&gt;&lt;/td&gt;
            &lt;td&gt;&lt;strong&gt;Can Be Hosted From&lt;/strong&gt;&lt;/td&gt;
            &lt;td&gt;&lt;strong&gt;Can Load These Assembly Types&lt;/strong&gt;&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
            &lt;td&gt;x86&lt;/td&gt;
            &lt;td&gt;x86 or x64 Operating Systems&lt;/td&gt;
            &lt;td&gt;x86, &amp;quot;Any CPU&amp;quot;&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
            &lt;td&gt;x64&lt;/td&gt;
            &lt;td&gt;x64 Operating Systems&lt;/td&gt;
            &lt;td&gt;x64, &amp;quot;Any CPU&amp;quot;&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
            &lt;td&gt;IA-64&lt;/td&gt;
            &lt;td&gt;Itanium Operating Systems&lt;/td&gt;
            &lt;td&gt;IA-64, &amp;quot;Any CPU&amp;quot;&lt;/td&gt;
        &lt;/tr&gt;
    &lt;/tbody&gt;
&lt;/table&gt;
&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Or, alternatively:&lt;/p&gt;
&lt;p&gt;
&lt;table width="200" cellspacing="1" cellpadding="1" border="1"&gt;
    &lt;tbody&gt;
        &lt;tr&gt;
            &lt;td&gt;&lt;strong&gt;Assembly Type&lt;/strong&gt;&lt;/td&gt;
            &lt;td&gt;&lt;strong&gt;Can Run On&lt;/strong&gt;&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
            &lt;td&gt;&amp;quot;Any CPU&amp;quot; / MSIL&lt;/td&gt;
            &lt;td&gt;Any CLR&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
            &lt;td&gt;&amp;quot;x86&amp;quot;&lt;/td&gt;
            &lt;td&gt;x86 CLR Only&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
            &lt;td&gt;&amp;quot;x64&amp;quot;&lt;/td&gt;
            &lt;td&gt;x64 CLR Only&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
            &lt;td&gt;&amp;quot;IA-64&amp;quot;&lt;/td&gt;
            &lt;td&gt;IA-64 CLR Only&lt;/td&gt;
        &lt;/tr&gt;
    &lt;/tbody&gt;
&lt;/table&gt;
&lt;/p&gt;
&lt;p&gt;To find out if an assembly is x86-only, you can use the &lt;a href="http://msdn2.microsoft.com/en-us/library/ms164699(VS.80).aspx"&gt;CorFlags.exe&lt;/a&gt; utility which ships with the .NET SDK. You can also use this tool to tweak the assembly type, although doing this will break strong named assemblies and generally cause chaos.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;When loading a.NET-based process, the .NET Framework decides which version of the CLR to load based on the assembly type. Processes based on &amp;quot;Any CPU&amp;quot; assemblies will load in the native CLR for the host system.&lt;/p&gt;
&lt;p&gt;This can lead to some funny situations. For example, the ASP.NET Development Server application is 32-bit only, so any web sites you run on it will run in the x86 CLR. On the other hand, on x64 IIS can run either 32- or 64-bit ASP.NET applications. This means you can move your ASP.NET application from the Development Server to IIS &lt;em&gt;on the same machine&lt;/em&gt;, and all of a sudden you will get a BadImageFormatException when an assembly refuses to load any more.&lt;/p&gt;
&lt;h2&gt;The Twist:&lt;/h2&gt;
&lt;p&gt;Sometimes you get a FileNotFoundException instead. This is when you try to reference an Assembly which is in the GAC.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;... and you think &amp;quot;That's odd, I thought that assembly was in the GAC.&amp;quot; and you look in the GAC browser, and there it is:&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;img alt="GAC Viewer In Explorer" src="http://www.finalbuilder.com/blogimages/angus/GACViewer.png" /&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;... the key is the &amp;quot;Processor Architecture&amp;quot; column on the righthand side.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;As of .NET Framework 2.0, the CLR actually has &lt;a href="http://hoser.lander.ca/The+Wonders+Of+The+Whidbey+GAC++Part+I+Processor+Architecture.aspx"&gt;four different GACs&lt;/a&gt; - one for each architecture, and one for &amp;quot;Any CPU&amp;quot; MSIL Assemblies. You can see this quite literally if you &lt;a href="http://www.clariusconsulting.net/blogs/pga/archive/2006/04/05/685.aspx"&gt;disable the GAC Shell extension&lt;/a&gt;, and browse to the GAC directory.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Each version of the CLR can only load assemblies which exist in its own GAC, or in the architecture-agnostic MSIL GAC. If you try to load an assembly from a different GAC, you'll see the FileNotFoundException.&lt;/p&gt;</description></item><item><title>Windows Vista compatibility</title><link>http://www.finalbuilder.com/Resources/Blogs/PostId/658/Windows-Vista-compatibility.aspx</link><category>FinalBuilder</category><pubDate>Wed, 23 May 2007 05:00:00 GMT</pubDate><description>Now that FinalBuilder 5.5 is out, I've posted a short article detailing some of the things to keep in mind when using FB with Windows Vista and User Account Control (UAC.) The article can be found &lt;a href="http://www.finalbuilder.com/Resources/Articles/ID/27/FinalBuilder-and-Windows-Vista.aspx"&gt;here&lt;/a&gt;.&lt;br /&gt;
&lt;br /&gt;
On a more techy subject, most developers are probably already well and truly up to speed with Vista integration by now, but here are a few resources that I found invaluable while getting a grip on the concepts of UAC, manifests, elevation, virtualization, and the elevation prompt.&lt;br /&gt;
&lt;p&gt; &lt;/p&gt;
&lt;ul&gt;
    &lt;li&gt; &lt;a href="http://technet.microsoft.com/en-us/windowsvista/aa906021.aspx"&gt;User Account Control Overview&lt;/a&gt; at Microsoft TechNet. A good semi-technical (code-free) overview of&amp;nbsp; UAC.&lt;/li&gt;
    &lt;li&gt; &lt;a href="http://blogs.msdn.com/cjacks/archive/2006/09/08/exploring-manifests-part-2-default-namespaces-and-uac-manifests-in-windows-vista.aspx"&gt;Evolving the Software Organism: Default Namespaces and UAC Manifests in Windows Vista&lt;/a&gt;. Covers some gotchas when embedding a UAC manifest.&lt;/li&gt;
    &lt;li&gt; &lt;a href="http://weblogs.asp.net/kennykerr/archive/2006/09/29/Windows-Vista-for-Developers-_1320_-Part-4-_1320_-User-Account-Control.aspx"&gt;Kenny Kerr's Windows Vista for Developers (Part 4)&lt;/a&gt;. Great code summary of the two ways to request UAC elevation in Vista. Creating a process with an elevated token, or creating an elevated out-of-process COM object.&lt;/li&gt;
    &lt;li&gt; &lt;a href="http://www.microsoft.com/downloads/details.aspx?FamilyID=BA73B169-A648-49AF-BC5E-A2EEBB74C16B&amp;amp;displaylang=en"&gt;Windows Vista Application Development Requirements for User Account Control Compatibility&lt;/a&gt;. 500-pound-gorilla Word document, covers everything you ever wanted to know (and then some.)&lt;/li&gt;
    &lt;p&gt;&amp;nbsp;&lt;/p&gt;
    &lt;p&gt;
    Happy Vista-ing!&lt;/p&gt;
&lt;/ul&gt;</description></item><item><title>Mixing up FinalBuilder with Team System (no more XML files!)</title><link>http://www.finalbuilder.com/Resources/Blogs/PostId/656/Mixing-up-FinalBuilder-with-Team-System-no-more-X.aspx</link><category>FinalBuilder,TFS</category><pubDate>Thu, 17 Aug 2006 14:00:00 GMT</pubDate><description>One of the comments that we frequently hear from users is "I couldn't do &lt;em&gt;xyz&lt;/em&gt; with MSBuild, but I can now with FinalBuilder."&lt;br /&gt;
&lt;br /&gt;
This is great, but hardly surprising. FinalBuilder includes out-of-the-box support for many more tools and processes than MSBuild. Not to mention that it has a GUI to set up your build process - no more editing XML files!&lt;br /&gt;
&lt;br /&gt;
Lately, though, an increasing number of our users are moving to Microsoft Team System. One of the cornerstones of the Team System process is the Team Foundation Build engine, which is built on top of MSBuild.&lt;br /&gt;
&lt;br /&gt;
Now, the Team Foundation Build wizard is fine if you only need to create simple build processes. Get some files, build some solutions, deploy some binaries to a file share. If you need to do anything more, though (and who doesn't?), then you're stuck back in XML land... The same applies if you want to edit your build processes after you've created them.&lt;br /&gt;
&lt;br /&gt;
Plain XML editing, with no built-in support for third-party tools, no support for data processing, no support for parallelisation, FTP transfers, Active Scripting, structured exceptions, recursion or Windows system functionality...&lt;br /&gt;
&lt;br /&gt;
FinalBuilder to the rescue!&lt;br /&gt;
&lt;br /&gt;
The Team Foundation Build engine allows you to add custom MSBuild tasks at any stage of your build process. This means that, with just a couple of lines of XML, you can &lt;span style="text-decoration: underline;"&gt;move your entire Team Build process&lt;/span&gt; to FinalBuilder! FinalBuilder can be used in place of MSBuild to provide functionality at &lt;span style="text-decoration: underline;"&gt;every stage&lt;/span&gt; of the Team Foundation build process (fetch, compile, test &amp;amp; deploy.) What's more, it all fits perfectly within the Team System framework!&lt;br /&gt;
&lt;br /&gt;
To see how, take a look at the walkthrough I just wrote: &lt;a href="/articles.aspx?mid=370&amp;amp;ctl=ArticleView&amp;amp;articleId=20"&gt;Integrating FinalBuilder with Microsoft Team Foundation Build&lt;/a&gt;.&lt;br /&gt;
&lt;br /&gt;
... Happy building!</description></item><item><title>File Dependencies</title><link>http://www.finalbuilder.com/Resources/Blogs/PostId/654/File-Dependencies.aspx</link><category>FinalBuilder</category><pubDate>Thu, 17 Nov 2005 01:18:00 GMT</pubDate><description>&lt;p&gt;Have you ever wished you can have your build check whether or not files have changed, so you know whether or not to rebuild?&lt;/p&gt;
&lt;p&gt;With &lt;a href="http://www.finalbuilder.com/finalbuilder/FB4Beta.html"&gt;FinalBuilder 4&lt;/a&gt;,&amp;nbsp;you now&amp;nbsp;can! Check out the new File Dependency action (you will need the latest public beta.)&lt;/p&gt;
&lt;p style="text-align: left;"&gt;&lt;img alt="Sample Project" src="http://www.finalbuilder.com/blogimages/angus/filedep/DemoProject.gif" /&gt;&lt;/p&gt;
&lt;p&gt;This is a skeleton action list&amp;nbsp;that does&amp;nbsp;two things:&lt;/p&gt;
&lt;ol&gt;
    &lt;li&gt;It synchronizes&amp;nbsp;a local copy of the source files&amp;nbsp;(via SurroundSCM Get.)
    &lt;/li&gt;
    &lt;li&gt;It&amp;nbsp;checks the file dependencies to see if anything has changed. Lets&amp;nbsp;zoom in on the File Dependency action:&lt;/li&gt;
&lt;/ol&gt;
&lt;p style="text-align: center;"&gt;&lt;img alt="Source Files" src="http://www.finalbuilder.com/blogimages/angus/filedep/FilesToCheck.gif" /&gt;&lt;/p&gt;
&lt;p style="text-align: left;"&gt;In &lt;strong&gt;Files and Folders to check&lt;/strong&gt;, I'm telling FinalBuilder to look at the modification dates of all the main FinalBuilder source and resource&amp;nbsp;files.&amp;nbsp; Because I've chosen &lt;strong&gt;Recurse into subdirectories&lt;/strong&gt;, FinalBuilder&amp;nbsp;will scan&amp;nbsp;the subdirectories of&amp;nbsp;each for all files of&amp;nbsp;those&amp;nbsp;types.&lt;/p&gt;
&lt;p style="text-align: left;"&gt;So, how do we know if the files have changed?&lt;/p&gt;
&lt;p style="text-align: center;"&gt;&lt;img alt="Source Files" src="http://www.finalbuilder.com/blogimages/angus/filedep/DateToCompare.gif" /&gt;&lt;/p&gt;
&lt;p style="text-align: left;"&gt;As you can see, I've told FinalBuilder to&amp;nbsp;check for any files which have changed since the last time the action was run. In the &lt;strong&gt;Options&lt;/strong&gt; section, I've elected to have FinalBuilder ignore any files created within two minutes of the last run, to compensate for jitter in the modification dates.&lt;/p&gt;
&lt;p style="text-align: left;"&gt;You can see in the greyed-out&amp;nbsp;&amp;ldquo;&lt;strong&gt;Use date from file&amp;ldquo;&lt;/strong&gt; section that I could have elected to compare the modification dates of the compiled libraries, in order to be really sure whether or not to rebuild.&lt;/p&gt;
&lt;p style="text-align: left;"&gt;In fact, you can build a&amp;nbsp;simple continous integration tool with just one more action:&lt;/p&gt;
&lt;p style="text-align: center;"&gt;&lt;img alt="Poor Man's Continous Integration" src="http://www.finalbuilder.com/blogimages/angus/filedep/PoorMansContinuousIntegration.gif" /&gt;&lt;/p&gt;
&lt;p style="text-align: left;"&gt;Example1 re-schedules itself (using the Schedule Add action and the Windows Scheduler) to run 10 minutes after it finishes, but only starts a build if there are files that have changed.&lt;/p&gt;
&lt;p style="text-align: left;"&gt;Example 2 is&amp;nbsp;even simpler - it loops continously checking for changed files (with a short delay in between each loop.) I also put in a separate check so the help file is only rebuilt if it has changed.&lt;/p&gt;</description></item><item><title>CruiseControl.NET</title><link>http://www.finalbuilder.com/Resources/Blogs/PostId/653/CruiseControlNET.aspx</link><category>FinalBuilder</category><pubDate>Wed, 05 Oct 2005 02:46:00 GMT</pubDate><description>&lt;p&gt;I've also been working on a FinalBuilder plugin&amp;nbsp;for the open source continuous integration tool,&amp;nbsp;&lt;a href="http://ccnet.thoughtworks.com/"&gt;CruiseControl.NET&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;We're still testing the&amp;nbsp;plugin&amp;nbsp;right now, but it will be released&amp;nbsp;in time for FinalBuilder 4.&amp;nbsp;You can add a FinalBuilder project to CruiseControl.NET with just two XML tags!&lt;/p&gt;
&lt;p&gt;If you would like to beta test,&amp;nbsp;please&amp;nbsp;&lt;a href="mailto:support@finalbuilder.com"&gt;let us know&lt;/a&gt;.&lt;/p&gt;</description></item><item><title>New XML Actions</title><link>http://www.finalbuilder.com/Resources/Blogs/PostId/652/New-XML-Actions.aspx</link><category>FinalBuilder</category><pubDate>Wed, 05 Oct 2005 02:32:00 GMT</pubDate><description>&lt;p&gt;I'm now into my fourth month here at VSoft, so it must be about time for a first blog post!&lt;/p&gt;
&lt;p&gt;I've been working on all kinds of new actions for FinalBuilder 4. I think lots of you who requested features will be very happy with the upcoming release (and everyone else should find something useful, too.)&lt;/p&gt;
&lt;p&gt;Today I just wanted to demonstrate two new XML actions : the XML Iterator&amp;nbsp;and the XML Read from Variable Action. Combined with the already strong XML support in FinalBuilder, you can work with data from almost any XML file. Allow me to demonstrate:&lt;/p&gt;
&lt;p&gt;Here's the project:&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="http://www.finalbuilder.com/blogimages/FB4_XMLIterator_project.gif" /&gt;&lt;/p&gt;
&lt;p&gt;The XML file I'm iterating is a 3Mb chunk of the &lt;a href="http://jv.wikipedia.org/"&gt;Javanese edition of the Wikipedia&lt;/a&gt;, exported as XML. I'm going to catalogue all the users who made edits, and record their usernames as well as any comments they recorded. I don't want to record revisions by the automatic MediaWiki bots.&lt;/p&gt;
&lt;p&gt;So, I iterate through the XPath /mediawiki/page/revision, saving the absolute XPath in to each revision in the 'Page' FinalBuilder variable:&lt;/p&gt;
&lt;p style="text-align: center;"&gt;&lt;img alt="" src="http://www.finalbuilder.com/blogimages/FB4_XMLIterator_xmliterator.gif" /&gt;&lt;/p&gt;
&lt;p style="text-align: center;"&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Once I have the absolute XPath to&amp;nbsp;each node, I can&amp;nbsp;read the 'Comment' and 'Contributor' tags into FinalBuilder variables. Here's the action which reads 'Comment':&lt;/p&gt;
&lt;p style="text-align: center;"&gt;&lt;img alt="" src="http://www.finalbuilder.com/blogimages/FB4_XMLIterator_readxmlvalue.gif" /&gt;&lt;/p&gt;
&lt;p&gt;The 'Comment' tag is optional, so I use a Try... Catch block to blank out the comment if there isn't one.&lt;/p&gt;
&lt;p&gt;Together with a 'Write Text File', these&amp;nbsp;actions are&amp;nbsp;all you need to create a list of contributors and their comments.&lt;/p&gt;
&lt;p &gt;This sort of technique can be used to parse any kind of XML file&amp;nbsp;as part of&amp;nbsp;your build process. If you need to, you can even create an XML file which gives instructions to your build process. But &lt;a href="http://nant.sourceforge.net/"&gt;who'd want to do that&lt;/a&gt;?&lt;/p&gt;</description></item></channel></rss>