gists, net, build, teamcity comments edit

I admit to loving me some good ol’ CruiseControl.NET for continuous integration but there’s just something to be desired from the UI and ease-of-use/ease-of-administration standpoint. CI Factory brings it a step closer to what I’m looking for, but after doing some evaluation, we ended up trying out TeamCity.

It’s awesome.

It’s easy to set up, easy to administer, flexible, customizable… really, the experience thus far has been pretty great. At work we’re testing it out with the free Professional edition, but if it works out on this project, we’ll be getting the full Enterprise edition. I know that if I set up a continuous integration server for CR_Documentor it’ll definitely be TeamCity.

That said, there are some differences in how you have to do things in TeamCity than if you’re working in CruiseControl.NET. Here’s what I’ve found so far. (Note - I’m using MSBuild in my code snippets. If you’re using NAnt or something else, you get to translate.)

$(CCNetLabel) becomes $(BUILD_NUMBER). In CruiseControl.NET you access the current build number (e.g., “”) with the variable $(CCNetLabel). In TeamCity, it’s $(BUILD_NUMBER). Something we’ve done to make this easier is creating a variable $(BuildLabel)` that we copy the appropriate value into at the beginning of the script. Doing that allows you to separate your build script from the build server proprietary variables.

Builds are generally done with agents. In CruiseControl.NET, if you want to run a private build you drop to the command line and build it yourself. In TeamCity, you can ship your changes off to the server to run a personal build. There is a variable provided $(BUILD_IS_PERSONAL) that will equal “true” if the build is running for an individual rather than as part of the “official” process. You’ll want to update your build script to accommodate both personal builds via agent and via command line.

This sample shows some MSBuild logic that sets a $(BuildLabel) property based on whether a build is personal or not. It also sets a $(CCNetLabel) property for backwards compatibility with scripts that might be using that.

  <Target Name="__EnvironmentSetup">
    <CreateProperty Condition="'$(BUILD_NUMBER)' == ''" Value="true">
      <Output TaskParameter="Value" PropertyName="BUILD_IS_PERSONAL"/>
    <CreateProperty Condition="'$(BUILD_IS_PERSONAL)' == 'true'" Value="">
      <Output TaskParameter="Value" PropertyName="BuildLabel"/>
    <CreateProperty Condition="'$(BUILD_IS_PERSONAL)' != 'true'" Value="$(BUILD_NUMBER)">
      <Output TaskParameter="Value" PropertyName="BuildLabel"/>
    <CreateProperty Value="$(BuildLabel)">
      <Output TaskParameter="Value" PropertyName="CCNetLabel"/>

Use the TeamCity test runner for better integration. While you can still use a straight call to, say, NUnit-Console.exe, you get very rich interaction and reporting in the TeamCity UI if you use the TeamCity version of the runner for your tests. You’ll want your script to “sniff” and see if it’s running on a developer box or in a TeamCity environment and use the appropriate runner.

This sample shows some MSBuild logic that builds an appropriate test runner command line for running NUnit 2.4.8 tests based on the environment. It assumes you have a list of test assemblies in a @(TestAsemblies) collection.

<PropertyGroup Condition="'$(BuildLabel)'!=''">
  <TestCommandLineArgs>v2.0 x86 NUnit-2.4.8 @(TestAssemblies->'%(FullPath)', ' ')</TestCommandLineArgs>
<PropertyGroup Condition="'$(BuildLabel)'==''">
  <TestCommandLineArgs>@(TestAssemblies->'%(FullPath)', ' ') /xml:TestResults.xml</TestCommandLineArgs>

There are two ways to integrate FxCop into the build. The first is to use the built-in FxCop build runner. This will run just FxCop though, and as a separate step. If you’re OK with not running FxCop as part of your CI build, that’s the easiest way to go. If you want to run the FxCop command line, though, and get the report into the UI, you need to use a “service message”

  • a message to Console.Out in a special format - to tell TeamCity where to get the report.

This sample shows what a service message to get FxCop command line output into TeamCity might look like.

  Text="##teamcity[importData id='FxCop' file='fxcop-report.xml']"
  Condition="'$(BuildLabel)'!=''" />

NCover support is manual. The stock TeamCity code coverage support is for EMMA. If you want NCover reporting to show up in the UI, there’s a little work to do. This blog entry shows a great in-depth how-to, but the simple version boils down to:

  1. Set up your HTML coverage report (e.g., the output from NCoverExplorer) to be published as a build artifact (along with your binary/compiled output).
  2. Update your TeamCity main-config.xml file to include the report. You’ll most likely want to comment out the other code coverage related report tabs since you probably won’t be using them.

For example, if you publish the report as “CoverageReport.html” then your main-config.xml file might have a line in it like:

<report-tab title="Code Coverage" basePath="" startPage="CoverageReport.html" />

You will probably also want to see a trend report of code coverage over time. To do that, you need to have your build script publish the data to TeamCity (again using “service messages”) and you need to add the custom graph to the build dashboard.

The MSBuild logic to publish the code coverage overall percentage to TeamCity looks like this. Note that in this example, it’s assumed that the output from NCoverExplorer has been written to “CoverageReport.xml”

  • adjust your paths as needed.
<XmlRead XPath="//coverageReport/project/@coverage" XmlFileName="CoverageReport.xml" Condition="Exists('CoverageReport.xml')">
  <Output TaskParameter="Value" PropertyName="CoveragePercent"/>
<Message Text="##teamcity[buildStatisticValue key='coveragePercent' value='$(CoveragePercent)']" Condition="'$(BuildLabel)'!=''" />

In your main-config.xml file, you then need to add the custom graph so it shows up in the build statistics page:

<graph title="Code Coverage">
  <valueType key="coveragePercent" title="% Coverage" />

The important bit there is that the value of “key” in the “service message” matches the value of “key” in the graph description.

Users set up their own notifications. In CruiseControl.NET, the build configuration specifies who gets alerted and to which build events. I hate that. I get all sorts of notifications I want because I happen to be on a mailing alias that was added administratively to the notification list. I can’t get out of it. In TeamCity, I get to configure my personal preferences for my notifications. This can be weird for some users who wonder why they’re not getting notified anymore

  • they need to do the work themselves to subscribe.

Users need to tie their TeamCity accounts to version control system accounts. There’s a lot of functionality in TeamCity that allows you to deal with “changes you made.” The way TeamCity figures this out is by each user providing a mapping of their TeamCity account to their username on the various version control systems they use. The “my changes” features won’t work for people that don’t set this up. (There is no analogous behavior in CruiseControl.NET.)

Builds aren’t done from working copies. In CruiseControl.NET when the build server checks out the source, the build is actually run from a live Subversion working copy. In TeamCity, the code still gets checked out from Subversion, but none of the Subversion admin directories (.svn) are there - it’s not a working copy, it’s an exported checkout. This is important if your build script tries to do anything with the version control system like inspect the location from which the current working copy was checked out. You can mitigate this in TeamCity by providing a custom environment variable (e.g., $(BUILD_VCS_ROOT)) that contains this information. It won’t be dynamic, but it’s the best you can do.

You can’t serialize builds. In CruiseControl.NET there’s a notion of a “build queue” such that if one build is running, it can “lock” a semaphore and other builds that require that semaphore won’t run until it’s free. That sort of thing is helpful if your build script dynamically registers third-party assemblies in the GAC for the duration of the build, for example. There is no such serialization mechanism in TeamCity.

You can get notified of build events via Google Talk. Technically the “Jabber” protocol, but Google Talk nonetheless. You’ll need to get your build server a Google account, but once you do, people can add that service account to their friends list and configure Google Talk notifications. They tell you how to do this in the TeamCity docs but they don’t tell you what to do if port 5222 (the Jabber port) is blocked off at your firewall - switch to port 80. Here’s what works for me:

  • Server:
  • Port: 80
  • Server user:

All in all, TeamCity is the advance in the build server that I was hoping would come along for CC.NET. It’s well worth the time to check out.

net, testing comments edit

Typemock Isolator 5.2 is out, and they’ve updated their mocking API to be more Visual Basic friendly. If you’re quick about it, you may even be able to procure yourself a free personal license.

Actually, they already have a pretty good blurb on it, so why don’t I just let them say it?

Programming Visual Basic applications?

Typemock have released a new version of their unit testing tool, Typemock Isolator 5.2. This version includes a new friendly VB.NETAPI which makes Isolator the best Isolation tool for unit testing A Visual Basic (VB) .NET application.

Isolator now allows unit testing in VB or C# for many “hard to test” technologies such as SharePoint, ASP.NET MVC, partial support for Silverlight, WPF, LINQ, WF, Entity Framework, WCF unit testing and more.

Note that the first 25 bloggers who blog this text in their blog and tell us about it, will get a Free Full Isolator license (worth $139). If you post this in a VB.NET dedicated blog, you’ll get a license automatically (even if more than 25 submit) during the first week of this announcement.

Go ahead, click the following link for more information on how to get your free license.

I already have a license, so I won’t be submitting my entry, but if you don’t have one, now’s a great opportunity to get Typemock Isolator for free.

GeekSpeak comments edit

I saw this over on Gizmodo (who saw it on BlogsDNA) and thought it’d be worth passing along. I haven’t gotten a chance to run Windows 7 myself, but for those who have and want to get Google Chrome running on the 64-bit version, you need to add the “–in-process-plugins” parameter to the chrome.exe command line.

aspnet, books comments edit

Professional ASP.NET 3.5 Security, Membership, and Role Management
with C# and
VBProfessional ASP.NET 3.5 Security, Membership, and Role Management with C# and VB is, other than a heck of a long title, probably one of the most useful books I’ve read through in recent memory.

You know when you’re working on an in-depth item related to, say, ASP.NET membership and you search the web only to find 100 tiny articles that almost cover what you’re looking for? You know how you wish someone would make a book that would just aggregate all of that knowledge and maybe take it just a little deeper?

This is that book.

The high level table of contents is as follows:

  • Chapter 1: Introducing IIS 7.0
  • Chapter 2: IIS 7.0 and ASP.NET Integrated Mode
  • Chapter 3: HTTP Request Processing in IIS 7.0 Integrated Model
  • Chapter 4: A Matter of Trust
  • Chapter 5: Configuration System Security
  • Chapter 6: Forms Authentication
  • Chapter 7: Integrating ASP.NET Security with Classic ASP
  • Chapter 8: Session State
  • Chapter 9: Security for Pages and Compilation
  • Chapter 10: The Provider Model
  • Chapter 11: Membership
  • Chapter 12: SqlMembershipProvider
  • Chapter 13: ActiveDirectoryMembershipProvider
  • Chapter 14: Role Manager
  • Chapter 15: SqlRoleProvider
  • Chapter 16: AuthorizationStoreRoleProvider
  • Chapter 17: Membership and Role Management in ASP.NET AJAX 3.5
  • Chapter 18: Best Practices for Securing ASP.NET Web Applications

The introductory chapters on IIS 7 were particularly interesting to me, since I still maintain a lot of legacy code on IIS 6 and haven’t had the opportunity to get in-depth with IIS 7 quite yet. These really gave a great overview not only of the general request process for IIS 7, but also differences between IIS 6 and IIS 7 with a focus on places where security-related events happen (e.g., where a request gets authorized, when the thread principal gets set, how these things get set in different scenarios).

Chapter 4 had a great discussion on the different ASP.NET trust levels that your application can run under and what each means. It also explained how the permissions for your application get determined and how to customize the permissions in your application to give it only what it needs. Code access security is such a tricky thing, it was nice to see this laid out in a clear fashion.

Chapter 5 talked about the way configuration (web.config) gets read and what permissions you need in order to access it. It also discussed ways to encrypt the sensitive sections of configuration (settings that might contain passwords, for example) and ways you can create your own encrypted settings provider - even allowing the settings to be read from a location other than the config file.

Chapter 6 on forms authentication started out like every other ASP.NET book with a forms auth discussion, but this chapter actually got into details like how secure encrypted forms auth tickets are and ways to influence the forms auth process that you might not have originally considered.

Chapter 7 might also have been called “How to get ASP.NET and classic ASP to coexist in IIS 7.” While the focus on it is getting the ASP.NET authentication mechanisms to work with classic ASP (using IIS 7), the discussion went a bit deeper than that, even talking about topics like passing data between ASP and ASP.NET.

Chapter 8 is basically everything you ever wanted to know about session state but were afraid to ask. It’s not just what session state is and how it works, it goes into what exactly is stored in a SQL session database, how that data gets generated, how to secure it, and how to stop session-related DoS attacks.

Chapter 9 was a short chapter that talked about a few odds and ends that didn’t get covered elsewhere. This chapter was the one that felt a little disorganized and mishmash, but it was still useful information. Topics here included request validation, viewstate protection, the permissions needed for page compilation, and securing your site map.

Chapters 10 - 16 were about the role and membership providers. The overall system gets introduced in a chapter, then each out-of-the-box provider gets explained in super detail. For example, the SqlMembershipProvider chapter goes so far as to explain how the schema for the membership database gets versioned. Chapter 17 ties the role and membership stuff into ASP.NET AJAX so you can see how to work with it all from the client side.

Chapter 18, though, is where you’ll want to flip right to. This is where it all comes together - all the stuff you’ll have learned from the previous chapters, put together in a near-checklist form, so you can take a step back from the application you’re working on, look through this, and ask yourself, “Am I doing this in a secure fashion?” Common gotchas and attacks are discussed here as well as ways to protect yourself.

It’s definitely not for folks new to ASP.NET - if you haven’t written an ASP.NET app before or you’re just starting out, this isn’t for you. This book gives you in-depth information that, in some cases, you’d only otherwise get by using .NET Reflector to delve into the actual .NET assemblies and follow the code. It’s heavy, detailed information. For mid-level to experienced ASP.NET developers, you definitely need to pick this up.

In all, this is one of those books I’m really glad to have on my shelf, right alongside Professional ASP.NET 3.5 in C# and VB.

personal comments edit

Well, Christmas is over, it’s the New Year, and it’s time once again to look back and see what went on for me in the last 365 days or so.

January 2008

I started January by updating my multi-user iTunes instructions to account for Vista and adding some similar multi-user instructions for Picasa. This setup is still working well for me today, in fact. We signed up for Verizon FiOS to save a little money and get a better Internet connection. Not sure if we’re actually saving that much, but the Internet connection is pretty cool. Now, if only they’d increase their HD on-demand offerings. Finally, I ended the month with Xbox problems, which is not uncommon for me.

February 2008

Lots of interesting developments happened with Typemock Isolator in February, particularly the addition of debugger integration, which is awesome. In the spirit of that, I blogged about how to get Isolator, NCover, and NUnit all playing nicely in MSBuild as well as a template for doing some quick Typemock Isolator testing. I fixed an issue with Sandcastle Help File Builder having multiple versions of the same dependency by creating a plugin.

March 2008

March saw me working a lot with Windows Workflow Foundation. I created a small series of articles called “Two Minute WF” to give a high-level overview of some of the things I found. We went to see the Cirque du Soleil show, “Corteo,’ which is fantastic and you absolutely must see it. We also had to get some birds pulled out of our eaves because they were nesting.

April 2008

We started the month by hitting the Shrine Circus, which I hadn’t been to since I was a kid. I posted a quick start for learning to use Typemock Isolator and played around with an Isolator-based product called “Ivonna” for testing ASP.NET pages. I also spoke at Innotech Oregon about Unit Testing with Typemock, which was a great experience - my first conference speaking gig. I started getting into Twitter enough to care to optimize my Twhirl experience. I figured out how to use the Composite Web Application Block without the whole Web Client Software Factory. Our printer went out, so I started looking at new ones but really didn’t find anything. Finally, we saw Jonathan Coulton in concert (and have tickets to see him again this month).

May 2008

May began with me spending a week in Liberty City. I love a good week of GTA, these being so fun, relaxing, and, frankly, cheap that most other vacations can’t beat it. That said, I used the Xbox until it pretty much killed the DVD drive, so I had to send it in and get my fifth Xbox 360. I was named a Typemock Expert (which is similar to the Microsoft MVP program, but for Typemock) - a real honor. At the end of May, we lost our kitty Jack to epinephrine reversal, which is extremely rare in cats. We still miss him.

June 2008

In June I finally stepped into the now and stopped carrying a separate cell phone and PDA, opting for the BlackBerry Curve. I still really like it, though I still have weird issues sometimes with the desktop synchronization software - something I never had a problem with when I was using a Windows Mobile PDA. I really started feelilng some slowdown issues on my work computer so I did a little research on the performance impact of full-disk encryption. I’m all for security, but I still think we need to have some faster hardware to compensate for the software overhead we’re required to keep. I showed you how to build a dynamic dependency list for an FxCop project using MSBuild. Finally, Dr. Horrible’s Sing-Along Blog was announced, and has turned out to be a web phenomenon. If you haven’t seen it, you owe it to yourself to take the time to go watch. I promise, you won’t be disappointed.

July 2008

In July I figured out how to fix the odd sign-in delay to Xbox Live that I was seeing - reboot the router. This is a trick that I still use… in fact, I had to do it last night. We saw Wall-E, which is my favorite Pixar movie so far. I’ve seen it a couple of times since and have it on Blu-ray. Love it. We did the Independence Day fireworks shoot in Walla Walla, WA, which was, as always, hard work but lots of fun at the same time. Plus, it’s always good to see my friend Greg and the rest of the fireworks gang. Once a year is just not enough. That said, I think we’ll be doing something a little closer to home this year if we can - Washington shows don’t count toward my pyro license renewal, and driving that far is really hard. (I’m not a big “car trip” person.) We got two new kittens, Kai and Stanley, and they have turned out to be real wild men. I moved my CR_SortLines and CR_JoinLines plugins into the DXCore Community Plugins project. I also released CR_Documentor 2.0 which included not only a Sandcastle preview style but also was my first release with CR_Documentor as open source. Since then, I’ve released a few bug fix builds and made the internal rendering engine much stronger, all with help from the community. (I’m always looking for contributors, so come on by and help if you can!) Finally, I turned 32. I don’t feel 32, but, well, I guess that’s just how it is.

August 2008

I started the month with a little epiphany about thinking in the abstract. I tried upgrading my blog to Subtext 2.0 and failed due to some permissions issues (which I believe have since been rectified… but I’m a little scared to try again since the previous attempt brought my site down for a couple of days). While I was working with it, though, I slimmed down my database, which had grown a lot and was bumping up against my alllocated size limit. Some things happened in my little circles of the tech world - Typemock Isolator announced an open source license and .NET Reflector got transferred to Red Gate. I picked up a Windows Home Server (which I still love) and I completed Grand Theft Auto 4 100%. Finally, I went on a team building field trip with the folks in my group and we had a blast. I have to say, the group I’m in is a fantastic team and I’m really proud to be with them. Great manager who really cares for the group, great team who comes together and really takes care of business. Best of the best.

September 2008

In September, besides my car getting hit, the big happening of note was that I finally solved my media server problem

  • all of my DVDs are now stored on a central server in VIDEO_TS format (so they’re not just the movies - they’re also disk backups) and can be played from a home theater PC in the living room. This was a lot of research and effort, but it turned out really well and has been really super cool to use. I can finally access my movies in the same way I can access every CD I have through my iPod and iTunes. (I have since found little issues that I’ve either solved or am working on solving, like some minor stuff with Vista not sleeping properly and the fact that my TV runs at 1366 x 768 but the HTPC outputs at 1280 x 768.)

October 2008

We started out by having some barkdust blown into our flower beds, something long overdue. We then spent a week in Disneyland and Legoland, which was simply amazing and tiring and fun all at the same time - a great vacation. I put a stick through my original Rock Band drums (and later ordered the Ion Drum Rocker kit, which has been so cool - I posted a comparison of the Ion drums vs. original Rock Band vs. Guitar Hero World Tour and the Ion drums are by far the superior choice). Oh, and we had 237 trick-or-treaters this year, a record. On a technical note, I posted some FxCop rule recommendations based on what works for me.

November 2008

After having participated in 2007 in the “Give One, Get One” program for the XO “One Laptop Per Child” program, I hadn’t done much with my XO laptop so I got the gumption up to get Ubuntu running on it. I showed you how to find tracks missing artwork in iTunes, and I also showed you how to read WCF configuration from an alternate location.

December 2008

Slightly late to the game, I realilzed what it takes to force ASP.NET 3.5 on IIS6. I posted a database maintenance page for Subtext to make trimming down the database size a little easier. (Remember the work I did in August?) I started running into a few problems with companies that think “Release Early, Release Often” also naturally implies that the external customer can take every upgrade that comes along without any cost. I had a little fun with the Amazon Universal Wish List button. I got my first 100% on drums in Rock Band. I talked a bit about storing configuration settings behind a WCF service. The year ended with a severe case of cabin fever after having been snowed in for several days.

Christmas was actually sort of spread out because of the snow (we’re still seeing presents we ordered for people trickling in via mail and UPS) and we weren’t able to get together with people because everyone was trapped, so the whole holiday felt a little weird. We still had a lot of fun and were able to see folks over the course of the following week, and everything was cleared up by New Years, when we went to a fun non-party party at our friends Jason and Tracy’s place.

As for the upcoming year, I suppose I have a few resolutions. I would like to try to blog more. Both more technical and more personal stuff, since I have a mixed audience (though I realize that sort of means “jack of all trades, master of none”). I’d like to get together more often with our friends - Angela and K, Jason and Tracy, Jason and Liz - and see some of the folks I don’t see nearly often enough a bit more often. I’d like to get better on the Rock Band drums, which sounds sort of dumb, but I didn’t go to band in high school so this is sort of my chance to learn to play an instrument, albeit a “fake instrument,” and see if it might be worth investing in getting the real electronic drum brain for my Ion kit. I’d like to take more time to do some of the hobbies I’ve let go - I used to draw, I used to do more art projects, I used to read more… it’d be nice to get back to some of that.

Anyway, 2008 was pretty good. 2009 looks to be interesting not only on a personal level, but on a global one - Obama’s been elected, the economy’s in the crapper, and we’re generally on the cusp of some major change. It’ll be an interesting time to see how it plays out. It makes me wonder if folks during the 60’s felt this same sort of feeling in the air of things changing and major events happening.