Roland Weigelt

Born to Code

  • LastBoxStanding 0.9.0

    Summary: LastBoxStanding is a Windows service that pings a configurable list of machines in your LAN to determine whether at least one of them is still running. If no machine responds, the service performs a custom action, e.g. a shutdown.

    Some time ago I built a server for my LAN from old parts (e.g. a P2B mainboard with a PII 400 and some RAM I had in a drawer). I use it for storing backup images and running SourceGear Vault (source control) and Dragnet (bug tracking) mainly used for my GhostDoc project. The server is not connected to a monitor and it’s really quiet (thanks to some hard-core silent modding), so it’s not uncommon that I simply forget to shut it down before going to bed. That usually means that the server keeps running until I come back from work the next evening – what a waste of electricity.

    I solved the problem by writing a Windows service to shut down the server automatically when it’s no longer needed, which is defined as when no other potential client on the LAN is running. The current version of LastBoxStanding can be configured to call any executable when the computer running the service is “the last box standing”.

    You can download the most recent version on the LastBoxStanding homepage.

    Update: Unfortunately, a small issue with 0.9.0 was found. If you set the check interval on your server to say 5 minutes, (re)start the service and then switch off all other machines on the LAN, LastBoxStanding does not perform the shutdown (or any other action you have configured). This is because the service has to reach at least one of the configured clients once and – this is the problem – the first check is not performed when the service starts, but after the (timer) interval has elapsed. If at that time none of the machines can be reached, LastBoxStanding assumes that the server is running standalone (e.g. for maintenance) where you don’t want the automatic shutdown.

    Even if this issue does not affect usage in “Real Life” that much, it’s a huge problem if people download LastBoxStanding and want to try it out. I’ll look into providing a fix this evening when I get back from work.

  • GhostDoc in Upcoming Book "Visual Studio Hacks" by James Avery

    Ok, now that the book “Visual Studio Hacks” by James Avery has been announced officially, I’m finally allowed to talk about my (small) contribution to the book: My Visual Studio add-in GhostDoc is one of the “hacks”.

    Shortly after GhostDoc won Roy Osherove’s Add-In contest in August 2004, James contacted me to write a quick run-down on using GhostDoc. He couldn’t offer any money (if you wonder why, you should read this), but hey – a few hours work for a free book isn’t too bad ;-)

    Let’s see what the editors at O’Reilly thought of my English writing skills (or lack thereof?) and what’s left of my original text…

  • Raising C# events doesn't feel right (and seems to have problems too)

    [This blog post was inspired by reading “Events, Delegate and Multithreading” by Brad Abrams.]

    I'm pretty sure the language designers thought about the whole thing way longer than I did, but from the very beginning raising events simply didn't "feel right". I’m not talking about the pattern of using “On…” methods — while that was something I (with an extensive Javascript background) had to get used to, it was a typical case of “what? whose idea was that? hmm, that’s not so dumb after all… hey, good idea!”.

    No, it’s the way of actually raising the event inside the “On…” method. In the blog post mention above Eric Gunnerson is quoted “We have talked about adding an Invoke() keyword to the language to make this easier, but after a fair bit of discussion, we decided that we couldn't do the right thing all the time, so we elected not to do anything”. Well, but that’s exactly what I’m missing: a keyword. While I don’t miss much from VB6 (ok, maybe the command window), I really miss the good ol’ RaiseEvent.

    When you look at source code, keywords are something that catch your eye. While you are bombarded with lots and lots of words (names of classes, variables, methods, etc. ), keywords like “delegate”, “event”, “throw”, “override” (man, I’m thankful for that one!) stand out — not only because of the coloring inside the editor, but also because of the different syntax compared to lines and lines of “variable = Method(parameter)”.

    For example throwing an exception:

    throw new FooException("bar");

    It says “throw” and you can virtually see some referees throwing a yellow flag.

    If I declare a delegate “FooHandler” and an event "Foo"

    public delegate void FooHandler(object sender, FooArgs e);
    public event
    FooHandler Foo;

    then one can argue the overall approach (is it too complicated yes/no?), but nevertheless it’s quite clear what the code is trying to tell me: This is a delegate, and this is an event, and there seems to be some connection between those two (because FooHandler appears in both).

    But then comes the big letdown: the code for raising the event. Until recently I would have used

    protected virtual void OnFoo(FooArgs e)
    {
    if (Foo != null)
    Foo(this, e);
    }

    Now I’ve read the recommendation to use

    protected virtual void OnFoo(FooArgs e)
    {
    FooHandler handler = Foo;
    if (handler != null)
    handler(this, e);
    }

    Sorry, but this doesn’t survive my personal test for “is the important stuff easily discoverable”: Step back from the monitor, squint your eyes until things look kind of blurry, and then collect all information you can get from what you see with a quick look. For fun, try it with the code example. While “throw new blah blah” and “public event blah blah blah” give you a rough idea of what’s happening, you have to look again to find out what “protected virtual blah handler handler blah handler null blah this” is all about. To avoid misunderstandings: This is not about understanding a programming language without learning it. What I’m talking about is browsing code really fast, looking at each line only fractions of a second, and not actually thinking about the code, but just matching some basic patterns inside your brain — stuff we’re all doing automatically when scrolling up and down while editing text.

    Ok, this post is longer than it should be, so let’s cut this whole thing short and get to the point:

    Comparing raising an event with the way how to throw an exception, and keeping in mind that the official wording (according to the Design Guidelines for Class Library Developers) is that exceptions are "thrown" and events are "raised", I would personally prefer:

    protected virtual void OnFoo(FooArgs e)
    {
    raise Foo(this, e);
    }

    What should the “raise” keyword do internally? Let me play the role of the unfair customer here: I don’t care, just make it work. I want to raise an event and that should work without the danger of a race condition or whatever.

     

  • GhostDoc News

    As mentioned on the GhostDoc homepage (which I use for the smaller status reports that also contain more private stuff), I’m back working on version 1.3.0. Since Christmas I have managed to spend a good amount of time on GhostDoc, but things are not progressing as fast as I had hoped. There are a couple of tough problems to solve that come with one of the major goals for 1.3.0: User-defined rules.

    In addition to user-customizable rules as mentioned in a previous post, it will be possible to define new rules by specifying regular expressions for matching e.g. method signatures, and templates containing macros for generating documentation texts. This may not be as flexible as writing new rules in C# code (which will have to wait until the framework has been stabilized), but there’s a lot that can be done with this simple solution.

    Things like upgrading from earlier versions (without losing customizations) and synchronizing configuration files between installations e.g. at home and at work turn out to be pretty tricky even though these topics already have been addressed in previous versions. Right now I’m busy refactoring and extending the code for reading/writing/importing/upgrading/merging configuration files, and hey — my existing unit tests actually caught a couple of nasty bugs and thus saved me a lot of time!

    To finish this post, here’s a screenshot showing the rule configuration tree (no new rules shown here, though):

    20050105_GhostDocRuleTree

    I’m far away from any release, which in turn is a chance for your suggestions and feature requests to be included in 1.3.0. Simply drop me a line in an email (ghostdoc at roland-weigelt.de).

     

  • Splitter Control with Drag Handle

    Here's some code straight from my work on GhostDoc that just has started again with new energy after a pause in the weeks before Christmas.

    I think most of us will agree that Splitter controls are really cool. Once you have learned the basics, there's virtually no excuse not to use them in your dialogs. The splitter itself is invisible, but in most cases users can easily guess where a splitter might be, and when the mouse pointer is over the splitter area, the pointer changes its shape indicating the direction in which the splitter can be moved:

    In some situations the use of a splitter is not that obvious:

    Would you expect the summary field to be resizable? In this case, it would be better to give the (first-time) user a hint showing a drag handle, e.g.:

    I needed a splitter like this for GhostDoc, fortunately writing one is extremely easy. Basically, all I had to do is to derive a new class from System.Windows.Forms.Splitter and override the OnPaint method. In case you're interested, you can download the source code and a small demo project here.

    Note that this control is ripped directly from the GhostDoc project and thus is not highly configurable. I changed the default docking to "top" matching the typical use case (other docking is still possible) and the thickness of the splitter is fixed. Simply regard the code as a good start for your own splitter control (e.g. if you want to change the drag handle's appearance).

    [Download]

  • The Power of First Impression

    After months of ZIPping up the GhostDoc source files every now and then, I finally have a source code management solution running (better late than never ;-). I've built and set up a server from spare parts, mainly to be used for storing files (e.g. backups and VMWare images), on which I installed SourceGear Vault. Using SourceSafe at work, this was an obvious choice for me. Usually I don't shy away from learning new things, but this time I didn't want to invest time to learn to use a system with a different philosophy (like e.g. SubVersion).

    Now I have to admit a few things: While there are quite a few things I'm really good at, I have no or only superficial knowledge when it comes to administering/configuring

    • databases
    • IIS
    • ASP.net applications

    So this is me, not wanting to invest a lot of time, and I want to install a product that

    • uses a database (MSDE in my case, which I have never installed before)
    • is running on IIS
    • is an ASP.net application

    And you know what? I got things running without any problems worth mentioning. The combination of a good installer (e.g. no editing of configuration files required) and an installation guide on the product's website with lots of screenshots enabled me to install this product. Creating a repository was also pretty easy and just a matter of minutes.

    So I'm happy to report that GhostDoc is now under source control.

    Maybe it turns out that I just installed the worst product imaginable. Maybe things go wrong from now on in every imaginable way. But right now I trust this product. It just feels right. From the splash screen (nice, but not too fancy) up to the help file (not really spectacular, but it was able to answer the few questions I had). Everything made good first impression.

    Now there's another application I installed on the server (I will not mention the name here, as it would be pretty unfair). When I start it, I get a "SqlException: SQL Server does not exist or access denied" error message. I couldn't find what to do in the documentation, the product's website does not have a FAQ, there's no forum, only a email address I can write to. This is what I'll to, because I'm pretty sure that once things are running, the application will be what I was looking for. But I guess you agree that the first impression is spoiled.

    As a developer I know that I'm completely unfair here, but as a customer (even though in both cases I don't have to pay as a single user) I don't care about being fair. Whether you like it or not, the first impression plays a vital role how users view your software.

    So do yourself a favor: When you release software (even if it's just a small tool), invest enough time in what could be called "the most important minutes" of your program. After a couple of months since the release of GhostDoc, I'm happy to notice people praise the "out of the box experience". Let me tell you it didn't come easy. Things weren't  perfect from a start and a lot of time and testing went into getting things right. I actually bought VMWare Workstation especially for testing GhostDoc on different system configurations (virtual machines simply rock, period). Did all the effort pay of? After all, I could have implemented lots and lots of features, so GhostDoc would produce less funny results in certain situations and would be as useful as I know it could be. But all I can say is yes, it was worth the effort. GhostDoc was downloaded a bit more than 1000 times (all versions combined) and while this may not be too impressive, I'm proud that I didn't receive a single question about the first steps. I receive bugs and feature requests regarding the text generation, people wanting to tweak things, people wanting to code their own rules, but not a single of those "I can't get it to run, what now?" questions that quickly eat away lots of time from actually developing software.

     

  • GhostDoc News

    While work on GhostDoc has slowed down a bit, I still haven't lost my enthusiasm for this project. It has proven to be useful for me in my daily work and feedback from users has been really positive so far. Most of the feature requests I receive are already on my TODO list, which I regard as a good thing as it shows that I'm on the right track with my plans. And it helps me to prioritize the items on the list -- so don't hesitate to drop me an email with your suggestion.

    Plans for 1.3.0

    The most wanted feature is proper handling of "On..." methods.... Oh yeah, this will be the next rule to be implemented and I plan to include it in 1.3.0. Interestingly, every person who wrote me about the funny mess the current version of GhostDoc is producing of e.g. "OnClosing" had a different idea of what the generated text should look like. Which leads to another problem: The more text GhostDoc actually adds to a simple processing of identifier names, the more people wish to change these additional texts to their liking (quite understandably).

    That's why version 1.3.0 will allow users to customize generated texts by editing template texts containing macros for dynamic content. The macros are similar to those for the pre-build and post-build steps in the Visual Studio IDE. For example, the template text for the summary of a constructor is "Creates a new $(DeclaringTypeName.ShortNameAsSee) instance". As in Visual Studio, you don't have to type out the macro name, but can select it from a list (or, to be more exact, from a tree).

    Here's what selecting a macro for e.g. the summary of a property will look like this (more or less, the screen shot is from a dialog in a GUI test, not the actual addin):

    As usual I won't talk about a release date; when I feel comfortable releasing 1.3.0, I'll release it ;-)

     

  • GhostDoc 1.2.1 released

    While working on version 1.3.0, I ran across some minor issues in 1.2.0 that were pretty easy to fix. These fixes are now available in version 1.2.1.

    Download: on the GhostDoc homepage

    What's New:

    • Fixed: Under certain circumstances, acronyms used in parameter names that are referenced in summary texts are not handled correctly (the first character of the acronym is shown in lowercase).
    • Added: Better visual feedback after pressing "Import" and "Upgrade" buttons during setup, now the wait cursor appears while the determining the differences between the two configuration (current/imported or default/imported).
  • What do you use for bug/issue tracking of your private projects?

    Currently I'm using an Excel sheet for keeping track of bugs and change requests for my Visual Studio Add-in GhostDoc. The worksheet was easy to set up and definitely does its job -- for now. But I'm not sure how things work out in a couple of weeks or months.

    Searching for "bug tracking freeware" on Google, there doesn't actually seem to be a shortage of tools I could try, given an infinite amount of time (which I don't have). So I'm asking the bloggers out there who have their little private pet project running for some time now: How do you keep track of things? I would definitely prefer something that doesn't require a web server.