<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://blogs.geekdojo.net/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/"><channel><title>Richard Case</title><link>http://blogs.geekdojo.net/rcase/default.aspx</link><description>Ramblings in a BizTalk &amp; .NET world</description><dc:language>en-GB</dc:language><generator>CommunityServer 2.0 (Build: 60217.2664)</generator><item><title>MsDtc error &amp; BTS Configuration Wizard</title><link>http://blogs.geekdojo.net/rcase/archive/2005/04/21/7911.aspx</link><pubDate>Thu, 21 Apr 2005 17:28:00 GMT</pubDate><guid isPermaLink="false">8c778905-0e18-4c86-9fd6-6e26bc083633:7911</guid><dc:creator>rcase</dc:creator><slash:comments>3</slash:comments><comments>http://blogs.geekdojo.net/rcase/comments/7911.aspx</comments><wfw:commentRss>http://blogs.geekdojo.net/rcase/commentrss.aspx?PostID=7911</wfw:commentRss><description>&lt;P&gt;Whilst trying to setup a small multi-box BizTalk environemnt within Virtual Server 2005&amp;nbsp;this week i've encountered a really annoying error whilst applying my BizTalk configuration settings. The configuration wizard would fail with the following error &lt;/P&gt;
&lt;P&gt;&lt;/P&gt;&lt;PRE class=code&gt;
"Failed to Deploy BizTalk system assembly "C:\Program Files\Microsoft BizTalk 
Server 2004\Microsoft BizTalk.GlobalPropertySchema.dll". 

A Microsoft Distributed Transaction Coordinator Problem prevented Connection
to the Configuration Database. The transaction has already been implicitly or
explicitly committed or aborted. 

[MicrosoftBizTalk.Deployment.DeploymentException] Cannot opent database 
BizTalkMgmtDb on server BTSDB &lt;/PRE&gt;
&lt;P&gt;&lt;/P&gt;
&lt;P&gt;It turns out this&amp;nbsp;is because i had copied the same virtual hard disk for use as the base for each of the virtual machines in my environment. Essentially MsDtc on each of the virtual machines has the same identifiers and therefore cannot communicate with each other. Does anyone know of the internals at all? &lt;/P&gt;
&lt;P&gt;To overcome this i re-installed MsDtc on each of the virtual machines before i installed anything. This is done by running the following within a command prompt (after which i rebooted):&lt;BR&gt;msdtc -uninstall&lt;BR&gt;msdtc -install &lt;/P&gt;&lt;img src="http://blogs.geekdojo.net/aggbug.aspx?PostID=7911" width="1" height="1"&gt;</description><category domain="http://blogs.geekdojo.net/rcase/archive/category/233.aspx">Biztalk</category></item><item><title>Creating a custom NAnt task</title><link>http://blogs.geekdojo.net/rcase/archive/2005/01/06/5971.aspx</link><pubDate>Thu, 06 Jan 2005 08:41:00 GMT</pubDate><guid isPermaLink="false">8c778905-0e18-4c86-9fd6-6e26bc083633:5971</guid><dc:creator>rcase</dc:creator><slash:comments>4</slash:comments><comments>http://blogs.geekdojo.net/rcase/comments/5971.aspx</comments><wfw:commentRss>http://blogs.geekdojo.net/rcase/commentrss.aspx?PostID=5971</wfw:commentRss><description>&lt;p&gt;
  &lt;style type="text/css"&gt;
pre.code
{
    background-color:#CCCCCC;
    padding: 10px;
}
pre.code .key
{
 color:Blue; 
}
pre.code .typ
{
 color:Navy;
}
pre.code .met
{
 color:Maroon;
}
pre.code .var
{
 color:Gray;
}
pre.code .str
{
 color:Olive;
}
pre.code .num
{
 color:Olive;
}
pre.code .val
{
 color:Purple;
}
pre.code .prg
{
    color:Blue; 
    cursor:pointer;
}
pre.code .prt_coll
{
 color:DarkGray;
 cursor:pointer;
 border:1px solid DarkGray;
 background-color:White;
}
pre.code .prt_vis
{
 color:Black;
 border:none;
}
pre.code .cmt
{
    color:Green;
}
  &lt;/style&gt;
I've been using NAnt quite a bit lately for automated builds on projects that I have been working on. If like me you require functionality that isn't already within NAnt (or NAntContrib) then you need not worry as it's really easy to write your own custom NAnt tasks to accomplish pretty much anything you could want.&lt;br&gt;
&lt;br&gt;
This post will take you through the creation of a task that I recently wrote called &lt;strong&gt;xmllist&lt;/strong&gt; . I created the task as I wanted to be able to read a list of port names from a BizTalk binding file (which is an xml document) and then loop round this list starting/stopping the ports:&lt;/p&gt;
&lt;p&gt;
&lt;pre class="code"&gt;
    &amp;lt;xmllist property=&amp;quot;ports.list&amp;quot; doc=&amp;quot;${binding.file}&amp;quot; selection=&amp;quot;//SendPort/@Name&amp;quot; /&amp;gt;    
    &amp;lt;foreach item=&amp;quot;String&amp;quot; delim=&amp;quot;,&amp;quot; in=&amp;quot;${ports.list}&amp;quot; property=&amp;quot;port.name&amp;quot;&amp;gt;    
        &amp;lt;exec program=&amp;quot;cscript.exe&amp;quot; failonerror=&amp;quot;false&amp;quot; commandline=&amp;quot;/nologo ${scripts.path}\StartSendPort.vbs ${port.name}&amp;quot;/&amp;gt;   
    &amp;lt;/foreach&amp;gt;
&lt;/pre&gt;
&lt;br&gt;
  &lt;br&gt;
  The steps required to create the task are:&lt;br&gt;
&lt;/p&gt;
&lt;p&gt; 1. Create a new &lt;em&gt;Class Library&lt;/em&gt; project&lt;br&gt;
  2. Change the project properties so that the name of the output assembly ends with Tasks.dll (i.e. &lt;a title="" href="http://www.solidsoft.com" target="_blank"&gt;Solidsoft&lt;/a&gt;.Build.Tasks.dll). &lt;strong&gt;If you don't do this NAnt will not find your tasks.&lt;/strong&gt;&lt;br&gt;
  3. Add a reference to &lt;em&gt;NAnt.Core.dll &lt;/em&gt;found in the NAnt bin directory. This assembly contains the base classes and attributes that are required to build a NAnt task.&lt;br&gt;
  4. Rename the class file to XmlListTask.cs&lt;br&gt;
5. At the top of the class file add the following using statements:&lt;/p&gt;
  &lt;pre class="code"&gt;
  &lt;span class='key'&gt;using&lt;/span&gt; &lt;span class='typ'&gt;NAnt.Core&lt;/span&gt;;
  &lt;span class='key'&gt;using&lt;/span&gt; &lt;span class='typ'&gt;NAnt.Core.Attributes&lt;/span&gt;;
  &lt;/pre&gt;
&lt;p&gt; 6. We need to inherit our class from one of the NAnt base task classes. There are a number that we can use depending on our requirements - for our task we will use Task (I will be covering using TaskContainer in a future posting).&lt;br&gt;
  7. Next we need to add the &lt;em&gt;TaskName&lt;/em&gt; attribute to our class definition. The purpose of this is to specify the tag name used for our task in a NAnt script. In our case we will use xmllist:&lt;/p&gt;
  &lt;pre class="code"&gt;
    [&lt;span class='typ'&gt;TaskName&lt;/span&gt; (&lt;span class='str'&gt;"xmllist"&lt;/span&gt;)]
    &lt;span class='key'&gt;public&lt;/span&gt; &lt;span class='key'&gt;class &lt;/span&gt;&lt;span class='typ'&gt;XmlListTask&lt;/span&gt; : &lt;span class='typ'&gt;Task&lt;/span&gt;
    {
  &lt;/pre&gt;
&lt;p&gt; 8. Each NAnt task can have a number of properties. These are represented in the NAnt build file as attributes of the task element. We will have the following properties:&lt;/p&gt;
&lt;div align="left"&gt;
  &lt;table width="400" border="1"&gt;
    &lt;tr&gt;
      &lt;td width="52"&gt;property&lt;/td&gt;
      &lt;td width="332"&gt;Used to specify the name of the property that the list of values should&lt;br&gt;
    be stored in&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;doc&lt;/td&gt;
      &lt;td&gt;The document that should be used&lt;br&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;selection&lt;/td&gt;
      &lt;td&gt;The XPath expressions that is used to select the values for the list.&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/table&gt;
&lt;/div&gt;
&lt;p&gt;Adding a property to your task is easy. For example, for the 'doc' property we would define a string property within our class. Then we use the &lt;em&gt;TaskAttribute&lt;/em&gt; attribute to specify the name of the attribute that will be used in the NAnt build file to map back to the property in the class that we just created:&lt;br&gt;
&lt;pre class="code"&gt;
    [&lt;span class='typ'&gt;TaskAttribute&lt;/span&gt; (&lt;span class='str'&gt;"doc"&lt;/span&gt;, &lt;span class='var'&gt;Required&lt;/span&gt; = &lt;span class='key'&gt;true&lt;/span&gt;)]
    [&lt;span class='typ'&gt;StringValidator&lt;/span&gt; (&lt;span class='var'&gt;AllowEmpty&lt;/span&gt; = &lt;span class='key'&gt;false&lt;/span&gt;)]
    &lt;span class='key'&gt;public&lt;/span&gt; &lt;span class='typ'&gt;string&lt;/span&gt; &lt;span class='var'&gt;XmlDocument&lt;/span&gt;
    {
      &lt;span class='key'&gt;get&lt;/span&gt;
      {
        &lt;span class='key'&gt;return &lt;/span&gt;&lt;span class='var'&gt;m_xmldoc&lt;/span&gt;;
      }
      &lt;span class='key'&gt;set&lt;/span&gt;
      {
        &lt;span class='var'&gt;m_xmldoc&lt;/span&gt; = &lt;span class='var'&gt;value&lt;/span&gt;;
      }
    }
  &lt;/pre&gt;
  Properties can be optional or mandatory. To mark a property as required (the user must use the attribute in the build file) you can add &lt;em&gt;Required = true&lt;/em&gt; to the attribute - as we have done above. By default properties are optional.&lt;br&gt;
  &lt;br&gt;
  You will also see that I have used the StringValidator attribute. This allows us to catch the situation where the attribute has been defined without a value (e.g. &amp;lt;xmllist doc=&amp;quot;&amp;quot; /&amp;gt;). NAnt will see that no value has been supplied and will stop the build with an error.&lt;br&gt;
  &lt;br&gt;
  Add code to create the &lt;em&gt;property&lt;/em&gt; and &lt;em&gt;selection&lt;/em&gt; properties - both of which are strings.&lt;br&gt;
&lt;/p&gt;
&lt;p&gt; 9. Now we get to the interesting bit - the part that actually performs the task. When you run your NAnt build file and it encounters your task it will first read the attributes of the task and populate the relevant properties in your class. Then it will execute your task by calling &lt;em&gt;ExecuteTask&lt;/em&gt;. You will need to override the &lt;em&gt;ExecuteTask&lt;/em&gt; method of the base &lt;em&gt;Task&lt;/em&gt; class. Within this method you place the code to do what ever it is that your task does. In our case create a comma delimited list of values from an xml document. The code I used is below:&lt;/p&gt;
 &lt;pre class="code"&gt;
 &lt;span class='key'&gt;protected&lt;/span&gt; &lt;span class='key'&gt;override&lt;/span&gt; &lt;span class='key'&gt;void &lt;/span&gt;&lt;span class='met'&gt;ExecuteTask&lt;/span&gt;()
    {
      &lt;span class='cmt'&gt;//Check the file exists&lt;/span&gt;
      &lt;span class='typ'&gt;string&lt;/span&gt; &lt;span class='var'&gt;docPath&lt;/span&gt; = &lt;span class='typ'&gt;Project&lt;/span&gt;.&lt;span class='met'&gt;ExpandProperties&lt;/span&gt;(&lt;span class='var'&gt;m_xmldoc&lt;/span&gt;, &lt;span class='var'&gt;Location&lt;/span&gt;);
      &lt;span class='key'&gt;if&lt;/span&gt; (&lt;span class='typ'&gt;File&lt;/span&gt;.&lt;span class='met'&gt;Exists&lt;/span&gt;(&lt;span class='var'&gt;docPath&lt;/span&gt;) == &lt;span class='key'&gt;false&lt;/span&gt;)
      {
        &lt;span class='key'&gt;throw &lt;/span&gt;&lt;span class='key'&gt;new &lt;/span&gt;&lt;span class='typ'&gt;BuildException&lt;/span&gt;(&lt;span class='str'&gt;"The xml document specified does not exist"&lt;/span&gt;);
      }
      &lt;span class='cmt'&gt;// Load the document and run the selection&lt;/span&gt;
      &lt;span class='typ'&gt;XmlDocument&lt;/span&gt; &lt;span class='var'&gt;doc&lt;/span&gt; = &lt;span class='key'&gt;new &lt;/span&gt;&lt;span class='typ'&gt;XmlDocument&lt;/span&gt;();
      &lt;span class='var'&gt;doc&lt;/span&gt;.&lt;span class='met'&gt;Load&lt;/span&gt;(&lt;span class='var'&gt;docPath&lt;/span&gt;);
      &lt;span class='typ'&gt;XmlNodeList&lt;/span&gt; &lt;span class='var'&gt;list&lt;/span&gt; = &lt;span class='var'&gt;doc&lt;/span&gt;.&lt;span class='met'&gt;SelectNodes&lt;/span&gt;(&lt;span class='var'&gt;m_selection&lt;/span&gt;);
      &lt;span class='typ'&gt;Project&lt;/span&gt;.&lt;span class='met'&gt;Log&lt;/span&gt;(&lt;span class='typ'&gt;Level&lt;/span&gt;.&lt;span class='var'&gt;Info&lt;/span&gt;, &lt;span class='str'&gt;"Found "&lt;/span&gt; + &lt;span class='var'&gt;list&lt;/span&gt;.&lt;span class='typ'&gt;Count&lt;/span&gt;.&lt;span class='met'&gt;ToString&lt;/span&gt;() + &lt;span class='str'&gt;" nodes"&lt;/span&gt;);
      &lt;span class='typ'&gt;System&lt;/span&gt; &lt;span class='var'&gt;builder&lt;/span&gt; = &lt;span class='key'&gt;new &lt;/span&gt;&lt;span class='typ'&gt;System.Text.StringBuilder&lt;/span&gt;();
      &lt;span class='key'&gt;foreach&lt;/span&gt; (&lt;span class='typ'&gt;XmlNode&lt;/span&gt; &lt;span class='var'&gt;node&lt;/span&gt;&lt;span class='key'&gt; in &lt;/span&gt;&lt;span class='var'&gt;list&lt;/span&gt;)
      {
        &lt;span class='var'&gt;builder&lt;/span&gt;.&lt;span class='met'&gt;Append&lt;/span&gt;(&lt;span class='typ'&gt;node&lt;/span&gt;.&lt;span class='var'&gt;InnerText&lt;/span&gt;);
        &lt;span class='var'&gt;builder&lt;/span&gt;.&lt;span class='met'&gt;Append&lt;/span&gt;(&lt;span class='str'&gt;","&lt;/span&gt;);
      }
      &lt;span class='key'&gt;if&lt;/span&gt; (&lt;span class='var'&gt;builder&lt;/span&gt;.&lt;span class='var'&gt;Length&lt;/span&gt; &gt; &lt;span class='num'&gt;0&lt;/span&gt;)
      {
        &lt;span class='var'&gt;builder&lt;/span&gt;.&lt;span class='var'&gt;Length&lt;/span&gt; -= &lt;span class='num'&gt;1&lt;/span&gt;;
      }
      &lt;span class='key'&gt;if&lt;/span&gt; (&lt;span class='typ'&gt;Project&lt;/span&gt;.&lt;span class='typ'&gt;Properties&lt;/span&gt;.&lt;span class='met'&gt;Contains&lt;/span&gt;(&lt;span class='var'&gt;m_property&lt;/span&gt;) == &lt;span class='key'&gt;true&lt;/span&gt;)
      {
        &lt;span class='typ'&gt;Project&lt;/span&gt;.&lt;span class='var'&gt;Properties&lt;/span&gt;[&lt;span class='var'&gt;m_property&lt;/span&gt;] = &lt;span class='var'&gt;builder&lt;/span&gt;.&lt;span class='met'&gt;ToString&lt;/span&gt;();
      }
      &lt;span class='key'&gt;else&lt;/span&gt;
      {
        &lt;span class='typ'&gt;Project&lt;/span&gt;.&lt;span class='typ'&gt;Properties&lt;/span&gt;.&lt;span class='met'&gt;Add&lt;/span&gt;(&lt;span class='var'&gt;m_property&lt;/span&gt;, &lt;span class='var'&gt;builder&lt;/span&gt;.&lt;span class='met'&gt;ToString&lt;/span&gt;());
      }
    }
 &lt;/pre&gt;
&lt;p&gt; &lt;br&gt;
  I won't take you through every line as it should be self explanatory. The main thing to note is the use of the &lt;em&gt;Project&lt;/em&gt; class throughout the method. The &lt;em&gt;Project&lt;/em&gt; class is used to represent the project that is being run and it's what we use to access most project related stuff (i.e. project properties).&lt;br&gt;
  &lt;br&gt;
  The &lt;em&gt;ExpandProperties&lt;/em&gt; method is used to ensure that any properties (not sure what NAnt properties are then go &lt;a href="http://nant.sourceforge.net/release/latest/help/fundamentals/properties.html"&gt;here&lt;/a&gt;) that are included as expanded to their actual value. For example, &lt;em&gt;${nant.project.basedir}&lt;/em&gt; will be replaced with the path to the directory where the NAnt script is located.&lt;br&gt;
  &lt;br&gt;
  The &lt;em&gt;Log&lt;/em&gt; method is used to output messages to the log file / screen - useful for informing the user what is happening and for debugging purposes. You can specify a log level - for example you can have messages that are only shown if are running NAnt in verbose mode.&lt;br&gt;
&lt;/p&gt;
&lt;p&gt; 10. Build the project and copy the assembly to the NAnt bin directory. If you plan to debug it then additionally copy across the pdb file. That's it.&lt;/p&gt;
&lt;p&gt; &lt;hr&gt;
  &lt;p&gt;I use 2 methods to debug my custom tasks: &lt;br&gt;
    &lt;/p&gt;
  &lt;/p&gt;
  &lt;p&gt; 1. Copy the assembly (and pdb) file to the NAnt bin directory. Open your solution in Visual Studio that contains the source for your task. Place your breakpoints. Go to the project properties and open the &lt;em&gt;Debugging&lt;/em&gt; page. Change the &lt;em&gt;Debug Mode&lt;/em&gt; to &lt;em&gt;Program&lt;/em&gt; and the &lt;em&gt;Start Application&lt;/em&gt; to the path to the NAnt executable (e.g. C:\Program Files\NAnt\bin\NAnt.exe). Then set the &lt;em&gt;working director&lt;/em&gt;y and/or &lt;em&gt;command line arguments&lt;/em&gt; so that NAnt will pick up your build file. Click run and away you go.&lt;br&gt;
  2. Place &lt;em&gt;System.Diagnostics.Debbugger.Break()&lt;/em&gt;; in your code before the line you want to break on. Re-compile the project and copy the assembly (and pdb) to the NAnt bin directory. When you run your NAnt script you should get a popup box asking you to choose a debugger. &lt;br&gt;
&lt;/p&gt;&lt;img src="http://blogs.geekdojo.net/aggbug.aspx?PostID=5971" width="1" height="1"&gt;</description></item></channel></rss>