CruiseControl.NET and Visual Studio - Quick Setup 
Up until now, my team has been using Visual Studio for all our test and build needs. We've used Visual Studio completely - test suites, solution files, etc. Recently we decided to start using CruiseControl.NET to put ourselves on the continuous integration path. What's the best way to get started quickly on CruiseControl without changing our workflow?

On the positive side, we use Subversion for our version control, which is supported right out of the box. It's very easy for us to create a new account and flag it for use of CruiseControl.net, because we run VisualSVN Server and we have active directory authentication set up.

Then the sacrifices came into play. We decided against using NANT to build our code. We have been successfully using Visual Studio 2008 to build / edit / test, and we didn't want to have to support both the Visual Studio style Solution / Project files (*.csproj, *.sln) as well as the NANT files. So that solution didn't work. Similarly, since we're using MSTEST (Microsoft's built-in test suite stuff), NUnit doesn't do everything we want.

Shame on us for using proprietary vendor code :) Anyways, turns out there is a good solution. Here's how it works.

1) Set up a desktop machine OR a Virtual PC image / VMWare image. We went with the Virtual PC solution since I could just run it on my local desktop. Microsoft publishes some stock Virtual PC Images of Windows XP that you can use.

2) Install the following programs - Subversion client, Visual Studio 2008, and CruiseControl.NET.

3) Create a new Subversion account on your repository named "CruiseControl", and grant it read-only access.

4) Edit your CCNet.config file (c:\program files\cruisecontrol.net\server\ccnet.config) to set up the project, the test solution, and launch CruiseControl as a service. We chose to send out build emails since we're still adopting the service and we need to get people used to it; eventually I'm sure folks will use the tray application.

5) You should probably copy up the files from your CruiseControl folder to your intranet server in a location where everyone can browse it. That helps you see statistics and build results.

Here's my sample CCNet.config file:

<cruisecontrol xmlns:cb="urn:ccnet.config.builder">
<queue name="Q1" duplicates="ApplyForceBuildsReplace"/>
<project name="DMT" queue="Q1" queuePriority="1">
<webURL>your intranet web server URL here</webURL>
<workingDirectory>a temporary directory here</workingDirectory>
<artifactDirectory>a different temporary directory here</artifactDirectory>
<modificationDelaySeconds>10</modificationDelaySeconds>

<triggers>
<intervalTrigger seconds="60" name="continuous" />
</triggers>

<sourcecontrol type="svn">
<executable>c:\program files\subversion\bin\svn.exe</executable>
<trunkUrl>your subversion repository location here</trunkUrl>
<workingDirectory>Where the code will go on your build machine</workingDirectory>
<username>cruisecontrol</username>
<password>your password here</password>
<revert>true</revert>
<cleanUp>true</cleanUp>
<tagOnSuccess>false</tagOnSuccess>
</sourcecontrol>

<tasks>
<msbuild>
<executable>c:\windows\microsoft.net\framework\v3.5\msbuild.exe</executable>
<workingDirectory>The application directory here</workingDirectory>
<projectFile>The name of the solution file</projectFile>
<targets>build</targets>
<timeout>300</timeout>
</msbuild>
<exec>
<executable>cmd.exe</executable>
<buildArgs>/c del /s/q c:\mstest-results.trx</buildArgs>
<description>This clears out the data from the previous MSTEST.EXE run.</description>
</exec>
<exec>
<executable>C:\program files\microsoft visual studio 9.0\common7\ide\mstest.exe</executable>
<buildArgs>/testcontainer:name of your test DLL file here /resultsfile:c:\mstest-results.trx</buildArgs>
<description>Run unit tests for your application and save the results to c:\mstest-results.trx</description>
</exec>
</tasks>

<publishers>
<merge>
<files>
<file>c:\mstest-results.trx</file>
</files>
</merge>
<xmllogger />
<statistics />
<modificationHistory onlyLogWhenChangesFound="true" />
<email from="fake send-from email address"
mailhost="smtp server goes here"
mailport="25"
mailhostUsername="cruisecontrol"
mailhostPassword="password goes here"
includeDetails="true">
<users>
<user name="Build List" group="buildmaster" address="your distribution list email address goes here" />
</users>
<groups>
<group name="buildmaster" notification="always"/>
</groups>
<modifierNotificationTypes>
<NotificationType>Failed</NotificationType>
<NotificationType>Fixed</NotificationType>
</modifierNotificationTypes>
<subjectSettings>
<subject buildResult="StillBroken" value="Build is still broken for {CCNetProject}" />
</subjectSettings>
</email>
</publishers>
</project>
</cruisecontrol>

  |  permalink  |  related link  |   ( 2.9 / 267 )
Scheduling Tasks on Windows 
In the old days I used to use the "AT" command to schedule simple recurring tasks for Windows. The "AT" command was simple enough but had some limitations, and for whatever reason it never seemed reliable, although maybe that was because I never treated it seriously.

As it turns out, Microsoft has replaced that with a new command called "SCHTASKS". Try this:

Start | Run
CMD.EXE
schtasks /query


You should see a message like this:

INFO: There are no scheduled tasks present in the system.


This just tells you that you do not have any scheduled tasks. Apparently, though, schtasks lets you set them up via the command line! Very useful. Of course, the alternative is to go Start | Control Panel | Scheduled Tasks and use the GUI; however I find many situations where I like to have the ability to execute changes automatically using the command line.

For more instructions on SCHTASKS, type "SCHTASKS /?" and you'll get a help page. The instructions seem good enough, so enjoy!

EDIT: Also note that when you're using SCHTASKS, quotes are escaped using the backslash. Here's an example of an escaped nested command:

schtasks /create /ru Administrator /rp 33d@r1294 /SC DAILY /TN "Download Scripts" /TR "C:\GamePulse\TaskRun.exe \"cmd.exe\" \"/c c:\gamepulse\running\download-scripts.cmd\" log %CUSTID% \"Download Scripts\""

  |  permalink  |  related link  |   ( 2.8 / 228 )
Save a DataTable to Excel Format 
Users of my applications like to get reports directly in native Excel so they can use them quickly. I typically save files in CSV, which is fast and reliable but Excel doesn't support it as thoroughly as it should.

On the other hand, using Excel automation to populate a file takes an eternity and doesn't work well on a server. So here's a nice middleground - I can save the file to an XML/HTML format that Excel supports natively.

This strategy solves a few problems:

1) Performance - This format is just as fast to create as CSV.
2) Dependence - Does not require using any Excel libraries.
3) Compatibility - Excel opens the file and it looks properly formatted and usable.
4) Data Integrity - CSV files tend to damage numeric or date values if they are formatted in a way Excel does not expect; this format converts everything to text which means the values are represented exactly.

You also have the option of using some of Microsoft Excel's number formatting tools. These are surprisingly hard to find documented anywhere! But, here they are:

http://www.ozgrid.com/Excel/CustomFormats.htm

Without further ado, here's the code:

/// <summary>
/// Save a DataTable to an XML file
/// </summary>
/// <param name="filename"></param>
/// <param name="dt"></param>
public static void SaveDataTableToExcelCompatibleFile(string filename, DataTable dt)
{
StreamWriter sw = null;
try {

// Create the file and write the header
sw = new StreamWriter(filename);
sw.WriteLine(@"<head><META http-equiv=""Content-Type"" content=""text/html; charset=UTF-8""></head><table>");

// Write column names
sw.Write("<tr>");
for (int i = 0; i < dt.Columns.Count; i++) {
sw.Write("<th filter=\"all\">");
sw.Write(dt.Columns[ i ].ColumnName);
sw.Write("</th>");
}
sw.Write("</tr>");

// Write data
for (int i = 0; i < dt.Rows.Count; i++) {
DataRow dr = dt.Rows[ i ];
sw.Write("<tr>");
for (int j = 0; j < dt.Columns.Count; j++) {
sw.Write("<td style=\"vnd.ms-excel.numberformat:@\">");
sw.Write(dr[j].ToString());
sw.Write("</td>");
}
sw.Write("</tr>");
}

// Write footer
sw.WriteLine(@"</table><br>
<br>Confidential Information - Do Not Distribute");

} finally {
if (sw != null) sw.Close();
}
}

  |  permalink  |  related link  |   ( 3 / 201 )
Firefox Performance Issues 
Has anyone noticed Firefox slowing down? Turns out a whole bunch of applications install firefox plugins without telling you. Here’s how to disable them.

1) From the main menu, select Tools | Add-Ons
2) Click the “Extensions” tab. Disable “Microsoft.NET Framework Assistant”.
3) Click the “Plugins” tab. Disable everything. None of them are needed.
4) Restart firefox. Your browser will be fast again!

I'm surprised a little to see a "Microsoft Office" plugin for Firefox. I wouldn't be surprised however to discover if that plugin slowed Firefox down a fair amount.
  |  permalink  |  related link  |   ( 3 / 189 )
Enable Compression for Windows Web Servers 
Since I've been in the web industry for so long, I can remember when enabling web site compression was complex and fraught with caching challenges. Apparently, compression is a performance win in pretty much every circumstance nowadays.

I created this script and called it "enable-compression.cmd":

cd c:\inetpub\adminscripts
cscript adsutil.vbs set w3svc/filters/compression/parameters/HcDoDynamicCompression true
cscript adsutil.vbs set w3svc/filters/compression/parameters/HcDoStaticCompression true
cscript adsutil.vbs set w3svc/Filters/Compression/GZIP/HcFileExtensions "txt" "css" "html" "htm" "js"
cscript adsutil.vbs set w3svc/Filters/Compression/GZIP/HcScriptFileExtensions "aspx" "asp"
iisreset /restart


Just in case any problems happened, I created "disable-compression.cmd":

cd c:\inetpub\adminscripts
cscript adsutil.vbs set w3svc/filters/compression/parameters/HcDoDynamicCompression false
cscript adsutil.vbs set w3svc/filters/compression/parameters/HcDoStaticCompression false
iisreset /RESTART


After you run these scripts, you restart IIS and watch as the performance benefits roll in.

To read more, Microsoft's Compression Article for IIS
  |  permalink  |  related link  |   ( 2.9 / 261 )

Back Next