<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:copyright="http://blogs.law.harvard.edu/tech/rss" xmlns:image="http://purl.org/rss/1.0/modules/image/">
    <channel>
        <title>MSBuild</title>
        <link>http://geekswithblogs.net/michelotti/category/6259.aspx</link>
        <description>MSBuild</description>
        <language>en-US</language>
        <copyright>Steve Michelotti</copyright>
        <managingEditor>stevemic21@yahoo.com</managingEditor>
        <generator>Subtext Version 0.0.0.0</generator>
        <item>
            <title>Build 64-bit MSI file on Cruise Control</title>
            <link>http://geekswithblogs.net/michelotti/archive/2007/03/17/109091.aspx</link>
            <description>&lt;P&gt;There is a known bug when trying to build 64-bit MSI files.&amp;nbsp; That is, the wrong InstallUtilLib.dll is embedded in the MSI.&amp;nbsp; A workaround to that problem is to use Orca to manually manipulate the MSI file in embed the correct version - the workaround is documented &lt;A href="http://blogs.msdn.com/heaths/archive/2006/02/01/64-bit-managed-custom-actions-with-visual-studio.aspx"&gt;here&lt;/A&gt;.&amp;nbsp; However, what if you want to automate this process on your build server?&amp;nbsp; Orca is a windows appication requiring user input.&amp;nbsp; &lt;/P&gt;
&lt;P&gt;To automate this from the command line, you can leverage a few lines of VBScript code that essentially duplicates the Orca functionality.&amp;nbsp; Specifically, what we are trying to do is embed the 64-bit version of InstallUtilLib.dll into the MSI so that the BadImageFormatException does not rear its ugly head.&amp;nbsp; The key line of the VBScript is the &lt;A href="http://blogs.msdn.com/heaths/archive/2006/02/01/64-bit-managed-custom-actions-with-visual-studio.aspx"&gt;SetStream&lt;/A&gt; method of the Record object.&amp;nbsp; The complete VBScript solution is shown below and can simply be invoked from CCNet using a standard command line task such as the &lt;A href="http://msdn2.microsoft.com/en-us/library/x8zx72cd.aspx"&gt;Exec&lt;/A&gt; MSBuild task with the appropriate command line arguments.&lt;/P&gt;
&lt;P&gt;Option Explicit&lt;BR&gt;On Error Resume Next&lt;/P&gt;
&lt;P&gt;Const msiViewModifyInsert&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; = 1&lt;BR&gt;Const msiViewModifyUpdate&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; = 2&lt;BR&gt;Const msiViewModifyAssign&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; = 3&lt;BR&gt;Const msiViewModifyReplace&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; = 4&lt;BR&gt;Const msiViewModifyDelete&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; = 6&lt;/P&gt;
&lt;P&gt;If (WScript.Arguments.Count = 0) Then&lt;BR&gt;&amp;nbsp;&amp;nbsp; Msgbox("No command line argument specified for MSI location. Please try again.")&lt;BR&gt;&amp;nbsp;&amp;nbsp; Wscript.Quit 1&lt;BR&gt;Else&lt;BR&gt;&amp;nbsp;AdjustInstallUtil()&lt;BR&gt;End If&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;public sub AdjustInstallUtil()&lt;BR&gt;&amp;nbsp;On Error Resume Next&lt;BR&gt;&amp;nbsp;&lt;BR&gt;&amp;nbsp;dim msiInstance : msiInstance = WScript.Arguments.Item(0)&lt;BR&gt;&amp;nbsp;dim installer : Set installer = CreateObject("WindowsInstaller.Installer") &lt;BR&gt;&amp;nbsp;dim installerDb : Set installerDb = installer.OpenDatabase(cstr(msiInstance), 1)&lt;BR&gt;&amp;nbsp;dim sqlCommand : sqlCommand = "SELECT * FROM Binary WHERE `Name`='InstallUtil'"&lt;BR&gt;&amp;nbsp;dim view : Set view = installerDb.OpenView(sqlCommand)&lt;/P&gt;
&lt;P&gt;&amp;nbsp;view.Execute()&lt;BR&gt;&amp;nbsp;dim record : Set record = view.Fetch()&lt;/P&gt;
&lt;P&gt;&amp;nbsp;If Not record Is Nothing Then&lt;BR&gt;&amp;nbsp;&amp;nbsp;const dataCol = 2&lt;BR&gt;&amp;nbsp;&amp;nbsp;record.SetStream dataCol, "C:\Program Files\CruiseControl.NET\64BitMSI\InstallUtilLib.dll"&lt;BR&gt;&amp;nbsp;&amp;nbsp;view.Modify msiViewModifyUpdate, record&lt;BR&gt;&amp;nbsp;&amp;nbsp;installerDb.Commit&lt;BR&gt;&amp;nbsp;End IF&lt;BR&gt;&amp;nbsp;&lt;BR&gt;&amp;nbsp;'clean up&lt;BR&gt;&amp;nbsp;Set installerDb = Nothing&lt;BR&gt;&amp;nbsp;Set view = Nothing&lt;BR&gt;&amp;nbsp;Set installer = Nothing&lt;BR&gt;&amp;nbsp;&lt;BR&gt;&amp;nbsp;'Error Handling&lt;BR&gt;&amp;nbsp;If Err.number &amp;gt; 0 Then&lt;BR&gt;&amp;nbsp;&amp;nbsp; Msgbox("Error while adjusting x64 InstallUtilLib: " &amp;amp; Err.Description &amp;amp; ": " &amp;amp; Err.Source &amp;amp; ": " &amp;amp; Err.number)&lt;BR&gt;&amp;nbsp;End If &lt;BR&gt;end sub&lt;BR&gt;&lt;/P&gt;&lt;p&gt;&lt;a href="http://www.pheedo.com/click.phdo?x=6cda6ad746d942b9a1110d0715a4fa12&amp;u=109091"&gt;&lt;img src="http://www.pheedo.com/img.phdo?x=6cda6ad746d942b9a1110d0715a4fa12&amp;u=109091" border="0"/&gt;&lt;/a&gt;&lt;/p&gt;&lt;iframe src="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Get&amp;amp;PageID=31016&amp;amp;SiteID=1" width=1 height=1 Marginwidth=0 Marginheight=0 Hspace=0 Vspace=0 Frameborder=0 Scrolling=No&gt;
&lt;script language='javascript1.1' src="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Get&amp;amp;Browser=NETSCAPE4&amp;amp;NoCache=True&amp;PageID=31016&amp;amp;SiteID=1"&gt;&lt;/script&gt;
&lt;noscript&gt;&lt;a href="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Click&amp;amp;Mode=HTML&amp;amp;SiteID=1&amp;amp;PageID=31016" target="_blank"&gt;
&lt;img src="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Get&amp;amp;Mode=HTML&amp;amp;SiteID=1&amp;amp;PageID=31016" width="1" height="1" border="0"  alt=""&gt;&lt;/a&gt;
&lt;/noscript&gt;
&lt;/iframe&gt;
&lt;img src="http://geekswithblogs.net/michelotti/aggbug/109091.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Steve Michelotti</dc:creator>
            <guid>http://geekswithblogs.net/michelotti/archive/2007/03/17/109091.aspx</guid>
            <pubDate>Sun, 18 Mar 2007 00:44:00 GMT</pubDate>
            <wfw:comment>http://geekswithblogs.net/michelotti/comments/109091.aspx</wfw:comment>
            <comments>http://geekswithblogs.net/michelotti/archive/2007/03/17/109091.aspx#feedback</comments>
            <slash:comments>1</slash:comments>
            <wfw:commentRss>http://geekswithblogs.net/michelotti/comments/commentRss/109091.aspx</wfw:commentRss>
            <trackback:ping>http://geekswithblogs.net/michelotti/services/trackbacks/109091.aspx</trackback:ping>
        </item>
        <item>
            <title>MSBuild with Cruise Control .NET - Part 2 (NUnit)</title>
            <link>http://geekswithblogs.net/michelotti/archive/2007/02/24/107224.aspx</link>
            <description>&lt;P&gt;In a previous post, I laid out our standard structure for MSBuild with Cruise Control.&amp;nbsp; Now I will show the details of FxCop and NUnit.&lt;/P&gt;
&lt;P&gt;Now you want to run FxCop:&lt;BR&gt;&lt;FONT color=#0000ff&gt;&amp;lt;Target Name="FxCop" DependsOnTargets="Build"&amp;gt;&lt;BR&gt;&amp;lt;Exec &lt;BR&gt;Condition="Exists('$(CCNetWorkingDirectory)\SolutionAnalysis.FxCop')" &lt;BR&gt;Command="fxcopcmd /p:&amp;amp;quot;$(CCNetWorkingDirectory)\SolutionAnalysis.FxCop&amp;amp;quot; /out:&amp;amp;quot;$(CCNetArtifactDirectory)\SolutionAnalysis-Fxcop.xml&amp;amp;quot;" &lt;BR&gt;WorkingDirectory="C:\Program Files\Microsoft FxCop 1.35"&lt;BR&gt;ContinueOnError="false"/&amp;gt;&lt;BR&gt;&amp;lt;Message &lt;BR&gt;Condition="!Exists('$(CCNetWorkingDirectory)\SolutionAnalysis.FxCop')" &lt;BR&gt;Text="This solution does not contain a SolutionAnalysis.FxCop file in the solution root." /&amp;gt;&lt;BR&gt;&amp;lt;Message Text="TestVar = $(TestVar)"/&amp;gt;&lt;BR&gt;&amp;lt;/Target&amp;gt; &lt;BR&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;You'll notice that this is looking for a "well-known" file called "SolutionAnalysis.fxcop" location in the root of our solution.&amp;nbsp; You may have 20 projects on CCNet - this enables a standard structure across all solutions.&amp;nbsp; If it doesn't find this file, it simply skips the step via the Condition attribute on the Exec task. This Exec task simply calls&lt;/P&gt;&lt;p&gt;&lt;a href="http://www.pheedo.com/click.phdo?x=6cda6ad746d942b9a1110d0715a4fa12&amp;u=107224"&gt;&lt;img src="http://www.pheedo.com/img.phdo?x=6cda6ad746d942b9a1110d0715a4fa12&amp;u=107224" border="0"/&gt;&lt;/a&gt;&lt;/p&gt;&lt;iframe src="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Get&amp;amp;PageID=31016&amp;amp;SiteID=1" width=1 height=1 Marginwidth=0 Marginheight=0 Hspace=0 Vspace=0 Frameborder=0 Scrolling=No&gt;
&lt;script language='javascript1.1' src="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Get&amp;amp;Browser=NETSCAPE4&amp;amp;NoCache=True&amp;PageID=31016&amp;amp;SiteID=1"&gt;&lt;/script&gt;
&lt;noscript&gt;&lt;a href="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Click&amp;amp;Mode=HTML&amp;amp;SiteID=1&amp;amp;PageID=31016" target="_blank"&gt;
&lt;img src="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Get&amp;amp;Mode=HTML&amp;amp;SiteID=1&amp;amp;PageID=31016" width="1" height="1" border="0"  alt=""&gt;&lt;/a&gt;
&lt;/noscript&gt;
&lt;/iframe&gt;
&lt;img src="http://geekswithblogs.net/michelotti/aggbug/107224.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Steve Michelotti</dc:creator>
            <guid>http://geekswithblogs.net/michelotti/archive/2007/02/24/107224.aspx</guid>
            <pubDate>Sun, 25 Feb 2007 01:37:00 GMT</pubDate>
            <wfw:comment>http://geekswithblogs.net/michelotti/comments/107224.aspx</wfw:comment>
            <comments>http://geekswithblogs.net/michelotti/archive/2007/02/24/107224.aspx#feedback</comments>
            <slash:comments>1</slash:comments>
            <wfw:commentRss>http://geekswithblogs.net/michelotti/comments/commentRss/107224.aspx</wfw:commentRss>
            <trackback:ping>http://geekswithblogs.net/michelotti/services/trackbacks/107224.aspx</trackback:ping>
        </item>
        <item>
            <title>MSBuild with Cruise Control .NET</title>
            <link>http://geekswithblogs.net/michelotti/archive/2007/02/23/107164.aspx</link>
            <description>&lt;p&gt;You want to set up a customizable, fully automated build process.&amp;nbsp; You want your build process to incorporate FxCop, NUnit, NCover, etc.&amp;nbsp;but you do not have the license for Team System.&amp;nbsp; No problem.&amp;nbsp; You can do all of this with free tools leveraging MSBuild and Cruise Control .NET (CCNet) as the basis of your solution.&amp;nbsp; This is not new news.&amp;nbsp; In fact, CCNet is probably the best known tool today to do automated builds.&amp;nbsp; However, there are lots of different ways to implement your build process.&amp;nbsp; I'm going to do a series of posts that provide a start to finish implementation of one way to set up your build server.&amp;nbsp; The posts will eventually include custom MSBuild tasks, custom CCNet add-ins, 32 bit / 64 bit considerations, and building MSI files with MSBuild.&amp;nbsp; In this post, I will just start with the primary structure and build process.&lt;/p&gt; &lt;p&gt;To kick&amp;nbsp;off the MSBuild process, you'll use the standard "msbuild" task provided by CCNet pointing to the custom MSBuild project file that we'll construct "ccnetMSBuild.proj":&lt;/p&gt; &lt;p&gt;&lt;font color="#0000ff"&gt;&amp;lt;tasks&amp;gt;&lt;br&gt;&amp;lt;msbuild&amp;gt;&lt;br&gt;&amp;lt;executable&amp;gt;C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\MSBuild.exe&amp;lt;/executable&amp;gt;&lt;br&gt;&amp;lt;workingDirectory&amp;gt;C:\CCNetArtifact\MyProjectName\Working&amp;lt;/workingDirectory&amp;gt;&lt;br&gt;&lt;/font&gt;&lt;font color="#0000ff"&gt;&lt;strong&gt;&amp;lt;projectFile&amp;gt;C:\Program Files\CruiseControl.NET\MSBuildScript\ccnetMSBuild.proj&amp;lt;/projectFile&amp;gt;&lt;br&gt;&lt;/strong&gt;&amp;lt;timeout&amp;gt;600&amp;lt;/timeout&amp;gt;&lt;br&gt;&amp;lt;buildArgs&amp;gt;/p:ProjectFile=$SolutionFile$&amp;lt;/buildArgs&amp;gt;&lt;br&gt;&amp;lt;logger&amp;gt;ThoughtWorks.CruiseControl.MsBuild.XmlLogger,C:\Program Files\CruiseControl.NET\server\ThoughtWorks.CruiseControl.MsBuild.dll&amp;lt;/logger&amp;gt;&lt;br&gt;&amp;lt;/msbuild&amp;gt;&lt;br&gt;&amp;lt;/tasks&amp;gt;&lt;/font&gt;  &lt;p&gt;&amp;nbsp;The basic outline of the msbuild script will be this:&lt;/p&gt; &lt;ol&gt; &lt;li&gt;Version assemblies in the current solution (details to come in a later post)  &lt;li&gt;Do a Debug build (if compile fails, stop build)  &lt;li&gt;Run FxCop on the solution  &lt;li&gt;Run NUnit on the solution  &lt;li&gt;Run NCover on the solution  &lt;li&gt;If everything has run successfully, do a Release build&lt;/li&gt;&lt;/ol&gt; &lt;p&gt;First, we utilize the standard msbuild task to do a Debug build.&amp;nbsp; Why do a Debug build before a Release build?&amp;nbsp; There are a couple of reasons.&amp;nbsp; First, Debug is the default mode for the developer on their local systems.&amp;nbsp; We encourage the developers to run FxCop locally before checking in - it's most convenient for them to be able to do this straight from Debug mode without having to first rebuild in Release mode.&amp;nbsp; Additionally, we typically will set our NUnit projects to build only in Debug mode but not in Release mode because we do not want to deploy NUnit projects out to a production environment.&amp;nbsp; Again, keeping it in Debug mode simplifies everything here.&lt;/p&gt; &lt;p&gt;This is the standard structure - in the interests of keeping this post a reasonable length, I will expand on the details on my next post...&lt;/p&gt;&lt;p&gt;&lt;a href="http://www.pheedo.com/click.phdo?x=6cda6ad746d942b9a1110d0715a4fa12&amp;u=107164"&gt;&lt;img src="http://www.pheedo.com/img.phdo?x=6cda6ad746d942b9a1110d0715a4fa12&amp;u=107164" border="0"/&gt;&lt;/a&gt;&lt;/p&gt;&lt;iframe src="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Get&amp;amp;PageID=31016&amp;amp;SiteID=1" width=1 height=1 Marginwidth=0 Marginheight=0 Hspace=0 Vspace=0 Frameborder=0 Scrolling=No&gt;
&lt;script language='javascript1.1' src="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Get&amp;amp;Browser=NETSCAPE4&amp;amp;NoCache=True&amp;PageID=31016&amp;amp;SiteID=1"&gt;&lt;/script&gt;
&lt;noscript&gt;&lt;a href="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Click&amp;amp;Mode=HTML&amp;amp;SiteID=1&amp;amp;PageID=31016" target="_blank"&gt;
&lt;img src="http://ads.geekswithblogs.net/a.aspx?ZoneID=5&amp;amp;Task=Get&amp;amp;Mode=HTML&amp;amp;SiteID=1&amp;amp;PageID=31016" width="1" height="1" border="0"  alt=""&gt;&lt;/a&gt;
&lt;/noscript&gt;
&lt;/iframe&gt;
&lt;img src="http://geekswithblogs.net/michelotti/aggbug/107164.aspx" width="1" height="1" /&gt;</description>
            <dc:creator>Steve Michelotti</dc:creator>
            <guid>http://geekswithblogs.net/michelotti/archive/2007/02/23/107164.aspx</guid>
            <pubDate>Sat, 24 Feb 2007 00:17:00 GMT</pubDate>
            <wfw:comment>http://geekswithblogs.net/michelotti/comments/107164.aspx</wfw:comment>
            <comments>http://geekswithblogs.net/michelotti/archive/2007/02/23/107164.aspx#feedback</comments>
            <slash:comments>3</slash:comments>
            <wfw:commentRss>http://geekswithblogs.net/michelotti/comments/commentRss/107164.aspx</wfw:commentRss>
            <trackback:ping>http://geekswithblogs.net/michelotti/services/trackbacks/107164.aspx</trackback:ping>
        </item>
    </channel>
</rss>