Monday, December 19, 2005

Using MSBuild - Don't learn from default build project file

If you are used to utilizing Ant or Nant to build your .net solutions, MSBuild is a fairly simple switch, though I still think Nant is more full-featured. However, the more I learn about MSBuild the less concerned I become with the available featureset.

One thing I did find confusing was the contents of the default build file generated by the VS IDE when you add a build type to a Team Project. This file is not a good way to learn about build files. First, it is based on a team foundation server based build. Second, it does not contain targets but depends entirely on the included targets file (Microsoft.TeamFoundation.Build.targets). This targets file can be valuable to learn from. I also recommend taking a peek at the MSBuild schemas (Microsoft.Buld.Core.xsd and Microsoft.Build.Commontypes.xsd)

If you build your own build file from scratch I believe you will find the experience more analogous to building with Nant. The thing about the default build file is that it is full of properties and item groups which have comments indicating how values should be specified to generate a proper build. However, this really only relates to the targets used by the included MS targets file. Great if you want a simple build, or don't care how its done. To learn the build syntax, throw away the default file and set about creating your own. I realize this is "wasted" effort since the default compile target is just fine but I prefer controlling everything and removing all 'MS Magic' from the project.

The MSDN docs are good enough to learn from, so I won't provide the basic info here. I will summarize a few basic thoughts:
  • Target has pretty much the same meaning as in Nant. There are other Nant analogies, especially with the built-in tasks. However, I would prefer to cover this in a more detailed explanation of Nant->MSBuild conversion issues.
  • ItemGroup collections can have any element content. The names of the elements within are used to dereference the value lists in a manner similar to properties.
  • ItemGroup children can have nested values that can be dereferenced with "dot" notation as in @(Parent.Child).
  • PropertyGroup collections allow any element content as with ItemGroup nodes. This allows a nice compact way to defining a property value, rather than indicating the value= attribute all the time.
  • The CSC task attributes are a little funny because they rename properties from the command line object they encapsulate. Strange choice, but if you know what csc requires at the command line you can figure it out. You can also read the docs, but who wants to do that?!
  • While learning, be sure and recognize the built in tasks, the reserved properties, and the well-known item metadata lists. You wouldn't want to recreate the wheel.
Submit this story to DotNetKicks

Wednesday, December 14, 2005

Dead DC Removal

There is a catch-22 you get into if you try to properly remove a domain controller when it has failed completely - either it is dead, or because of massive corruption it might as well be.

The funny thing is that in the tools ms recommends for this job you have to connect to the DC in question in order to demote it or cleanup its entries in AD. Silly. I finally found an answer though...

If this dead controller is one of your operations masters, well - good luck. If not, then you will need the tool ldp.exe. I hadn't seen this one before, but it basically allows you to edit the domain ADSI containers. The details are here:

http://computing.fusion13.com/ActiveDirectory/Remove-A-Domain-Controller-From-Active-Directory-With-LDP.shtml

Follow this post, and the dead server is gone. Other articles indicate that when you rebuild the machine, you should use a new name due to cached values on machines throughout the domain.
Submit this story to DotNetKicks

Thursday, December 01, 2005

Learning Team Foundation Source Control Coming From VSS

It has been a decent little adventure getting more than one developer at a time working with Team Foundation Source Control (or VersionControl - a little aside: it seems its all about version control when dealing with the web services API, but its called source control in the IDE UI).

Coming from VSS (or Source Unsafe, or Source Destruction - choose your favorite epithet) some things which are common in other control systems take some getting used to when first moving to "real" source control. My only other version control experience was with Perforce, and there are some parallels here. I have since also gotten into CVS while dealing with NUnit development, and there are other parallels here. If you come to TFSC from one of these other systems, the learning curve will be much more shallow.

Allow me to enumerate the lessons learned so far:
1. The folder you designate as a workspace for a certain project will be totally controlled by source control, including deletes. This is great (and normal for other version control systems), but a real adjustment for lazy VSS users who sometimes like to keep the development area dirty in order to work with different versions of code at the same time (mySource.cs.old for instance).
2. What you actually have on disk is of no consequence to the source control system. Which is to say that the notion of having the latest, or the content of a particular file is controlled by the actions which you have taken against source control through its interfaces. The information stored in the source control database will be used by the source control system, not a lookup of files on your disk. If you happen to do something on disk, outside of source control - you will soon be very confused when you go to use source control again. To get back to a usable state, you should choose "Get Specific Version", and then check the "Force get of file versions already in workspace" checkbox. This will "update" your disk, even if everything was up to date, and get you back in sync with what the source control system believes to be true. In short, don't do anything to the workspace outside of version control. If you want to play around with files, copy the workspace to another location.
3. Putting auto-generated folders or files in source control is unworkable. What used to simply be a problem or difficulty in VSS is totally unworkable in team system source control. This means all /bin, /doc, and /obj folders must be left out of source control. This is actually a tenant of good configuration management anyhow, but the problem is that by default when you add projects to source control, you will get these folders. You must consciously remove or avoid these folders.

A related issue is how you deal with assembly references when you are not including any of the referenced assemblies in these auto-generated folders. Your projects keep relative links to referenced assemblies in the

<HintPath>..\..\ReferenceAssemblies\Release\SomeAssembly.dll</HintPath>

element. Each developer (and the build server) will need to have this same relative path, or a gac entry for the referenced assembly. Another possibility is to use an environment variable so each developer can have their own locations, but this seems like more setup than its worth.

4. The entire team must standardize on file or url based projects when working with web projects. Because of the relative references in web.config and because of unit tests, all hell breaks loose if you have one developer using a url based web project, and another using the file system based. Choose one way to do it, and force all developers to accept this standard.

As far as which to choose, I would say the file based is better simply because it is keeps your web projects in the same basic location as your other projects, and because it is the way Visual Studio expects to work - and we all know that if you accept some product defaults, you'll save headaches.
Submit this story to DotNetKicks