SonghaySystem(::)

The Resource Location Manager: A Tiny C# Application That Solves the “Favorites Problem”

The tiny C# application summarized here is not the first C# application from Songhay System. It’s the first presentable C# application. Other Songhay solutions with C# is tied so closely to legacy data and relatively large and complex systems, that the task of simply presenting a C#—application for the sake of C#, introducing the .NET Framework—would be overshadowed by a long list of types and too many namespaces.

By no means is there time to waste trying to dream up a tiny application just for the sake of this article. So years after .NET 1.x is released, on the heels of the 2.0 release, this article presents a real 1.1 application, solving a real simple problem: the Favorites problem.

The Favorites Problem

At the beginning of 2004, my Desktop Start Menu displayed over 600 Favorites or bookmarks—from over 600 little text files. The challenge of placing these Favorites into one XML file to display them from a Desktop menu is easily solved by the .NET Framework. Underneath all the Web services and data grids is the primal power of XML. The opinion here is that this solution to the Favorites problem demonstrates the awesome primacy of XML. In fact, this solution goes beyond Internet bookmarks and preserves and executes shell commands as well. This ‘extra’ functionality is the main reason why this Application is regarded as a ‘resource location manager.’

The Class View

Class View

To accentuate the negative first, note the ExceptionHandler and SaveException types above—these types are not used by the Client type, the “main” application. They are hanging out as bloat because the Xml.Manager class has a dependency on them. This implies that our Xml.Manager is designed for larger, often server-based solutions and is currently not flexible enough to handle a tiny C# application like this one without a bit of bloat. Exceptions in this application are written directly to the screen as pop-up dialog boxes because only a few exceptions are expected.

Now, a few comments about each class in the Class View shown above:

The Songhay.Xml.Manager Class

This class is used to call routines for getting XML attribute values and node sets. The assumption here is that these routines are easier to use than what is offered by System.XML itself. There are others such as DonXML that have spent time developing a custom XML solution as well. Although time and opportunity has not permitted a thorough investigation of these products, what is certain is that System.XML requires customization for a particular solution. Surely our behavior is “by design”!

The Songhay.Reflection Class

The Songhay.Xml.Manager class depends on the Songhay.Reflection class. This is because the Songhay XML Manager has the ability to load XML from embedded resources. The LoadStream() member of Songhay.Reflection does this job.

The Songhay.WinForms.Managers.IconManager Class

This type is used to load an icon embedded as a resource in this application. The IconManager.ManifestIcon() member loads "Icons.Kinte.ico" in the constructor of Client. It follows that the Build Action of the icon is Embedded Resource.

The Songhay.WinForms.ResourceLocationManager.Client Class

This class is the application itself. The name “Client” indicates a Songhay System User Interface. The next section will highlight some of the features of this type.

Client Highlights

Unhandled Exceptions

The Client has an Application_ThreadException() handler. This implies the intention of implementing “best practices” for Windows Forms. This reveals a design meant to catch ‘all’ unhandled exceptions in the application. But according to Peter A. Bromberg, Ph.D. in “Getting Better Information on Unhandled Exceptions,” this handler is only one-fifth of the solution:

There are basically five ways I’ve identified so far that enable you to deal with UE’s (Unhandled Exceptions):

1. Putting Application.Run() in try-catch block

2. Using Application.ThreadException event

3. Using AppDomain.UnhandledException event

4. Add registry entry to pop up JIT Debugger

5. Use ADPLUS in crash mode with debug symbols installed.

Preventing Multiple Instances from Running

The following form of Client.Main() means to prevent multiple instances from running:

/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
    _mutex = new Mutex(true,"SonghayLinksClient");

    if(_mutex.WaitOne(0,false))
    {
        Client c = new Client();
        Application.ThreadException +=
            new System.Threading.ThreadExceptionEventHandler(Application_ThreadException);
        Application.Run();
    }
    else
        Application.Exit();
}

                    

Joseph M. Newcomer in “Avoiding Multiple Instances of an Application—Why FindWindow doesn’t work” has a broader discussion of relevant techniques.

_xmlLocal and _xmlRemote

Is this application a “Smart Client”? This tiny application loads and displays two XML files. A screenshot from an old Windows 2000 installation can be seen in the Blog entry “XML Favorites for Windows.” These XML file locations are defined in App.Config with the expectation that there will be a local file and a remote file.

The primary reason for this design is to secure command-line entries that are not URIs in a local, machine-dependent, XML file while sharing a remote, universal XML file. By the way, the same remote XML file used by this application is consumed via AJAX by the kinté links page of kintespace.com, the first Songhay System Web site.

The XML Schema Is Based on OPML

A ‘dialect’ of OPML 1.0 was used to store the bookmarks for this application. Our interpretation of Dave Winer’s outline element is that is can be ‘extended’ with any attribute. The my:uri attribute is therefore ‘attached’ to outline to provide locations for our “favorites.” The use of my for a namespace identifier should immediately hint to modern Microsoft Office users that there must be an InfoPath form supporting this XML file.

OPML, its generic design, promises to be the schema supporting almost all list-like data structures. The assumption here is its repeated use in InfoPath form design and in XPath expressions will speed up development time.

And speaking of XPath expressions, the key attributes prefixed with xpath_, in appSettings of App.config, are meant to make the compiled code somewhat schema independent. In other words, no XML elements are “hard-coded” in the “business logic.” All references to XML elements are stored in App.config.

Parsing XML Data with Regular Expressions

Some thought was devoted to how the command-line entries are processed in this application. This ‘thought’ resulted in the following logic:

MatchCollection matches = Regex.Matches(uri,@"""[^""]+""|\s+[\/-]\w+");

                    

This is the first step taken to locate the file part and the argument(s) part of a URI. So, for example, this is the entry for editing the HOSTS text file with Notepad++:

"C:\Program Files\Notepad++\notepad++.exe" %SystemRoot%\System32\DRIVERS\ETC\HOSTS

                    

The content inside the quotes is the file part and one argument follows a whitespace character. Also note that Environment.ExpandEnvironmentVariables() comes in handy here.

Handling Command-Line Arguments

The constructor of Client checks for environment variables with the following logic:

string[] args = Environment.GetCommandLineArgs();
this._useAltBrowser = (System.Array.IndexOf(args,"-altbrowser") != -1);

                    

So –altbrowser is the command line option that will open an ‘alternative’ browser instead of the default Internet Explorer. The alternative browser is declared in App.config in appSettings as:

<add key="alt_browser" value="C:\Program Files\Mozilla Firefox\firefox.exe" />

                    

Shutting Down When Windows Shuts Down

In “Sprinkle Some Pizzazz on Your Plain Vanilla Windows Forms Apps,” Bill Wagner writes:

If a user logs off Windows while your application is running, Windows will request that your application exit by raising the SessionEnded event. If you don’t respond to this event, Windows will assume your application just crashed. Windows will tell your users that your application is not responding, and will request to terminate it.

The following form of Client.Main() means to force this application to quit when windows shuts down:

private void SystemEvents_SessionEnded(object sender,SessionEndedEventArgs e)
{
   this._icon.Visible = false;
   Application.Exit();
}

                    

Enhancing the Application

Most of the desired improvements in this tiny application are down to the bare metal of Windows Forms itself:

Selected Links to Resources

Resource Location ManagerDownload the compiled assembly, the subject of this document.
You Don’t Need a ‘Main’ FormThis article from Ian Griffiths, co-author of Mastering Visual Studio .NET, provided the fundamental concepts that made this application conceivable.
TaskableThe design of this OPML application resembles our app. Taskable menu items look much better than what we have here. My guess is that Taskable is not written with .NET Framework 1.1. It looks like an unmanaged, Win32 application.
A Simple .NET TCP Socket ComponentThis article may lead to the next conceptual jump for this kind of application. Maybe not…
Using Resources in Visual Studio .NETDejan Jelovic writes, “Visual Studio .NET seems to have a weird model for adding and managing resources such as bitmaps and locale-specific strings. It doesn’t work in all the cases, it’s illogical, tool support is poor, and it’s badly documented.”
 
This document was last reviewed on Monday, January 23, 2006 at 01:56 PM PST.
Copyright© 2008 by Bryan D. Wilhite All rights reserved. No part of this material may be used or reproduced in any form or by any means, or stored in a database or retrieval system, without prior written permission of the publisher except in the case of brief quotations embodied in critical articles and reviews. Making copies of any part of this material for any purpose other than your own personal use is a violation of United States copyright laws.

The information provided by Bryan D. Wilhite at kintespace.com is provided “as is” without warranty of any kind. In no event shall Bryan D. Wilhite or any of his affiliates be liable for any damages whatsoever including, but not limited to, direct, indirect, incidental, consequential, loss of business profits or special damages due to material published by Bryan D. Wilhite or any of his affiliates.