Automate creation of an empty Visual Studio solution

I am by no means an expert at shell scripting, I use cygwin on my windows machine because I want to force myself to learn a cross-platform console environment. A simple thing that I was able to accomplish, which I am pretty pround of is being able to create an empty Visual Studio solution file from cygwin/bash.

As a prerequisite I have an empty Visual Studio solution, a .gitignore, and an .hgignore file synced in my dropbox folder. I have three functions setup to create a fresh solution, one without version control initialized, one with git initialized and one with mercurial initialized. All functions will create a folder with the first parameter passed in (eg. "new-sln solution_name_here") and under that folder will copy the empty solution with the first parameter as the name of the .sln file.

  • No version control initialized
  • With Git initialization
  • With Mercurial initialization

I love being able to automated simple tasks such as this. I hope you can find some of this helpful.

Setup NLog in 5 minutes

Here is a really easy way to write your first logs to a file using NLog:

  1. Right-click references
  2. Click on Manage NuGet References
  3. Make sure the "Online" tab on the left is selected, and search for "NLog"
  4. Install "NLog Schema for Intellisense(TM)" (this will automatically install an xml NLog.config and the xsd file for xml intellisense support and pull in the references needed for NLog) 
    01
  5. Open the automatically created NLog.config file and uncomment the sample target and rule, they should look like so:  
  6. Now you are all set up to log stuff, with the sample configuration whenever you log something it will append it to a {shortdate}.log file under the /logs directory where the executable is run, so if you did something like: 
  7. You'll end up getting this log file:
    02

NLog documentation can be found on the project's site. Happy logging!

 

Configuring MSBuild to Auto Update ClickOnce Installations

When we push an update to our ClickOnce application users would get a notification that the application has an update and are forced to have to click OK to accept the update. We don’t want this dialog box to show because it allows the user to Skip the update and it forces them to have to click OK to receive the update.

Image001

So I needed to figure out a way to force the update on our users, in order to do this I needed to set 3 properties when calling msbuild during our continuous integration process.

  1. MinimumRequiredVersion - Tells ClickOnce that when it updates this application it should update to this version (however this does not force ClickOnce to perform the update). As you can see we set this to the same version number that the ApplicationVersion is set to so that the MinimumRequiredVersion is always the latest version.
  2. UpdateMode=Foreground - Tells ClickOnce to update the application before it is opened.
  3. UpdateRequired=True - Tells ClickOnce to automatically perform the update.

When all 3 properties were set, the next time the user goes to open the application (via the shortcut in their start menu), ClickOnce will check for updates and automatically install the update while showing the progress indicator to the user. This forces the user to receive the updates and gives them visual notification that they are getting the updates.

Image002

Opening Visual Studio Solutions in Cygwin

I needed a quick way to open a visual studio solution file from within cygwin and this is what I’ve been able to come up with.

The first line ensures that the path to Visual Studio is accessible (devenv.exe) and the second line will start devenv with all solutions in the present working directory (I only ever have one solution file per project, if you have multiple for a project this would probably be annoying since it would open them all).

The ‘disown’ part is key, this forces bash to return to prompt without waiting for devenv to ‘exit’

With this set up all that I have to do is navigate to a directory that contains a .sln solution file and type 'sln' into cygwin.

Getting Date Time information in TeamCity build configurations

We wanted to integrate the datetime into our build numbers and TeamCity does not natively have date and time information available as part of a system property. Luckily there is a plugin that provides some access to this information called the Groovy plugin.


I will quickly go over how to install this plugin and customizing some of the date outputs.

  1. Download latest successful build of the plugin under the artifacts column here. Make sure to grab the groovyPlug.zip and the .jar files under the application_libs folder.
  2. Copy the groovyPlug.zip file into the BuildServer/plugins directory on the server hosting your TeamCity installation.
  3. Copy all of the .jar files that you downloaded from the artifacts into the webapps/ROOT/WEB-INF/lib directory in your TeamCity Home location.
  4. Restart the TeamCity Web Server Windows service.
  5. To verify that the plugin was installed successfully go and edit any build configuration in TeamCity and under the General Settings tab, you can click on the icon in the right-hand side of the Build number format textbox to pop open a list of available parameters, and you will see some additional parameters added by the Groovy plugin that allow you to access date and time information.

2010-10-11_14h26_11

Now, if you want to customize the formatting of how the date and/or time appears then you will need to customize the following file: BuilderServer/config/__groovyPlug__/GroovePropertiesProvider.groovy

Add your custom formatted date properties to line 75 (inside of the addBuildStartTime method). I've added the following formatted date properties...

Documentation to see how to format this date/time can be found here

Pretty simple, and now we can include date and/or time in our builds wherever we see fit (we are using them as part of our build number).

Encapsulating Lists in Entities

Working with Aggregate Roots really helps enforce integrity of your data since data manipulation is modeled as behaviors. Exposing a collection of entities that is being managed by the aggregate can be tricky though...

Let us say that you have an AddressBook aggregate that contains Contacts. You may want to expose the Contacts to a client (via an IEnumerable property) but modifactions to that list of Contacts should only be modeled as behaviors on the AddressBook (ie. the Add method implemented below).

You may feel that this is enough encapsulation to prevent modification to the list of Contacts, but you can still get access to the list of Contacts. All the client would have to do is cast the Contacts property to an IList<Contacts>, since all we are doing is passing the reference to our internal Contacts list out as IEnumerable.

A good way to prevent this is to return the contacts from our Aggregate via the yield keyword in C#. This forces the framework to dynamically create a new IEnumerable reference.

We can even go a step further by implementing a simple extension method. I called it ToEnumerable<T> as it has a similar feel as ToList<T>.

Now our property looks like so in our Aggregate, nice and clean =)

Domain-Driven Design Resources