Windows desktop alerts for remote Subversion repositories. A .NET 2.0 application in C#

Posted by jimblackler on Mar 27, 2008

An SVNWatch desktop alert

Part of my last job involved some management of a large code base. I wanted to keep an eye on activity on the Subversion source control database. In particular I wanted to know as soon as someone had checked in and what the changes were.

There are many plug-ins available for Subversion (also known as SVN) that will email interested parties when the repository changes, but my experience with these is that they create so many emails that people end up turning them off. Also, they need administrator access to the database which not everyone will have.

I hit on the idea for a “notifier” application for Subversion that would act like the gmail notifier, letting interested parties know as soon as an SVN database is changed. The Windows balloon alerts are ideal for this sort of thing, so I wrote an application for Windows Forms .NET 2.0 which I am ready to publish today.

SVNWatch

SVNWatch is a Windows application that provides desktop alerts when nominated SVN repositories are changed.

The application runs in the status bar. Alerts when the repositories change take the form of messages in status bar ‘balloons’, and a change in the appearance of the status bar icon.

Clicking on the status bar icon will display a list of the new SVN log entries since the last scan operation.

The application can watch an unlimited number of SVN repositories.

Prerequisites

SVNWatch requires two other components to be present on the user’s PC:

  1. The .NET Framework version 2. Vista comes with this pre-installed. For XP, this can be downloaded from the Microsoft website here.
  2. The Subversion Windows client software (“SVN.EXE”). This can be downloaded from the Tigris/Subversion website here.

    This is required because SVNWatch invokes the SVN.EXE to interface with the repositories, rather than using an internal static library. I had poor results getting the same results out of the standard API that are available through the SVN.EXE route.

The main dialog

The main dialog lists the watched repositories, provides options to manage the list and gives information about forthcoming scans.

The main SVNWatch window

Click on the ‘Add Repository’ toolbar button or from the Repository menu select Add.

A New Repository dialog will be shown. Under Monitor Url enter the URL of the repository, for instance http://svn.jimblackler.com/jimblackler/trunk.

Click OK to add and start monitoring the repository.

First time connection

SVNWatch will fetch and display the first batch of logs. If there is a technical problem connecting to the repository or fetching the logs, this will be displayed in the bottom of the main SVNWatch dialog.

Regular scans

As long as SVNWatch is running, it will regularly scan repositories for new logs
to report. The frequency of scans can be changed in the Settings.

When new logs are available a notification balloon will be shown in the task bar. If just one new log is seen, a quick summary of the check in comments will be shown. If more than one log is available, the number of logs available will be shown.

An alert just displaying the number of logs received

Clicking on the bubble will show a full and detailed list.

A full list of new logs

In addition, the task tray icon will change to indicate there are new logs that have not been viewed by the user.

If new logs are available, they can also be viewed by clicking on the View New Logs button.

Edit repository settings

Repository URLs or other settings can be edited at any time by selecting the repository in the main list and selecting Edit Repository.

The user can also view when the last scan was performed and what the outcome was. This can be useful for troubleshooting problems to do with database connection.

The Maximum Fetch value indicates the largest number of logs to download. This is necessary because some long-established SVN repositories are very large.

Settings

Settings, which include the repositories scanned, are automatically saved and retrieved. They are stored for each Windows user.

The settings file can be found in a location such as C:\Documents and Settings\User Name\Application Data\SVNWatch\settings.bin where User Name is the current logged in Windows user name.

The settings can be edited by selecting the Edit menu then the Settings menu item.

The settings dialog

Download

Download SVNWatch as an executable installer from here. Before running SVNWatch, go to the Tigris official Subversion website and download and install the Windows Subversion client (used by SVNWatch).

Alternatively, you may obtain the source code from my own SVN repository here. The project can be built with Visual Studio 2005 C# Express or other later versions of Visual Studio. SVNWatch and its dependent projects are open source, licensed under the LGPL.


Obtaining inline XML C# documentation at runtime using .NET 2.0

Posted by jimblackler on Mar 23, 2008

C# .NET provides a standard mechanism for programmers to inline XML documentation in their programs. Classes, functions, properties and more can be augmented with comments, and the build system creates amalgamated XML files accompanying the program output. A variety of tools such as Sandcastle can build help files from the data. Visual Studio 2005 and 2008 also supports the scheme with keyboard shortcuts and optional build warnings for missing comments.

  1. /// <summary>
  2. /// An example C# class
  3. /// </summary>
  4. /// <remarks>
  5. /// This class illustrates how a class can be marked up with inline C# comments
  6. /// </remarks>
  7. class SomeExampleClass
  8. {
  9.     /// <summary>
  10.     /// An example of a property
  11.     /// </summary>
  12.     public int ExampleProperty
  13.     {
  14.         get { return somePrivateVar; }
  15.     }
  16. }

Unfortunately, many programmers have observed that there’s no way to discover these comments at runtime by reflection. All manner of alternative information can be accessed with reflection – but not the XML comments.

The solution

This documentation can be discovered at run time with a little extra code, as I will demonstrate. The reason the comments can’t be discovered by reflection alone is because they are not included in the .NET assemblies (.EXE or .DLL files), but are conventionally included as .XML files to accompany the assembly files.

I’ve provided a simply class library for .NET 2.0 called DocsByReflection that will when possible return an XmlElement that describes a given type or member. This can be used to easily extract comments at runtime. Here’s an example of how:

  1. XmlElement documentation = DocsByReflection.XMLFromMember(typeof(SomeExampleClass).GetProperty("ExampleProperty"));
  2. Console.WriteLine(documentation["summary"].InnerText.Trim());

This would ouput “An example of a property”, extracted from the code comments in the code fragment at the top of the article.

The class works by locating the .XML file accompanying the assembly that defines the type or member (discovered using reflection). Then the .XML file is loaded into an XmlDocument, and the ‘member’ tags are scanned to find the one that refers to the target type or member. This tag is returned as an XmlElement which contains the free form XML that these comments can contain (e.g. including HTML markup).

This method relies on the existence, on disk, of the generated XML. It must have the same name and location as the generated .EXE or .DLL accompanying it – with only the extension changed. This will happen by default when building with Visual Studio, once documentation is enabled (see below). If you are distributing your program and expect the distributed version to discover the comments in run time, you must also distribute the XMLs alongside the executables. This is commonly seen in any case. Note that many of the framework executables (for instance those found in C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727) are accompanied by documentation XML files.

How to use

Download the library source as a zip file here, or use Subversion to update to the very latest version here and here.

(Updated 18/3/08 for bug fix – see comments).

Load the DocsByReflectionDemo.sln to see a simple example of how to use the library. This gathers and prints information about a class type, some functions, a property and a field.

Using in your own code

In Visual Studio, set up your own project that includes XML comments.

(Note that the XML documentation output is not enabled by default in Visual Studio. Go to your project properties, select Build, and under the Output section check the box that says XML Documentation File. It is very important that you do not change the location of the XML file or this method will not be able to locate it at run time.)

If you have not already, add the comments in Visual Studio. By default, pressing forward slash three times when the caret is positioned before the start of an element you wish to document (such as a class or method) will insert a documentation template for you before the start of the file.

Add the DocsByReflection project to your solution and a Reference to it from your project. Add the line “using JimBlackler.DocsByReflection;” to the top of your .CS file. The call se the functions DocsByReflection.XMLFromType() (for classes, structures and other types) and DocsByReflection.XMLFromMember() (for methods, properties and fields) to fetch XmlElement objects that represent the documentation for that type or member.

Query the returned object to read the documentation. For instance, xmlElement[“summary”].InnerText.Trim(). This locates the summary node, and uses the InnerText property of XmlElement to strip out any XML formatting that may be embedded in the comment. Also, Trim() or a regular expression can strip the unwanted whitespace from the comment.

Comments or problems

If you have any comments or problems with the library, please add a reply to this blog post and I will answer them here.


Allowing Enter or Return in controls such as TextBox when using Windows Forms .NET 2.0

Posted by jimblackler on Mar 6, 2008

A simple application overriding enter and return in a TextBox

Many applications feature text input boxes that used to accept input for immediate use by the program. For instance, a program might provide a dialog allowing user to search for text in a document. This would feature a text box to enter the text, and a button next to it labelled ‘search’ that would immediately act on the supplied text.

However many users will not want to click the ‘search’ button, but simply press Return or Enter after entering the text.

How can this be done in a C# .NET 2.0 Windows Forms application? One way is to set the Accept property in the parent form to refer to the ‘search’ button. This will make Enter / Return automatically press the button, when pressed in any child control on the form.

The events to override in the designer

This doesn’t always offer the level of control the application developer wants. Any control could activate the press, not just the relevant text box. It requires a button, which might not always be desirable. Also it is not trivial to allow multiple textboxes on a single form that all accept Enter / Return in that way.

The best way that I have found is to add a KeyDown event to the textbox and compare the pressed key with Keys.Enter. Then, act on that key and set SuppressKeyPress in the event arguments so that the system does not try to do anything further with the keypress. (Typically what happens otherwise is that an ‘error’ beep is played).

  1. private void textBox1_KeyDown(object sender, KeyEventArgs e)
  2. {
  3.     if (e.KeyCode == Keys.Enter && e.Modifiers == Keys.None)
  4.     {
  5.         // do something with textBox1.Text
  6.         e.SuppressKeyPress = true;
  7.     }
  8. }

However if you implement that code and run the application, you’ll find nothing happens when you press Enter. The reason is that the Enter key press never reaches the KeyDown event. This happens because certain key presses are reserved for system use. The solution is to supply a PreviewKeyDown event in the textbox. This gives the opportunity to override the system override as it were, and allow the key to reach the KeyDown even in the textbox.

  1. private void textBox1_PreviewKeyDown(object sender, PreviewKeyDownEventArgs e)
  2. {
  3.     if (e.KeyCode == Keys.Enter && e.Modifiers == Keys.None)
  4.     {
  5.         e.IsInputKey = true;
  6.     }
  7. }

I’ve provided source for an example application as a zip file. Requires Visual Studio 2005 or later, C# express will also work.

Download source code