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.
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.’

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:
Songhay.Xml.Manager ClassThis 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”!
Songhay.Reflection ClassThe 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.
Songhay.WinForms.Managers.IconManager ClassThis 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.
Songhay.WinForms.ResourceLocationManager.Client ClassThis 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.
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 block2. Using
Application.ThreadExceptionevent3. Using
AppDomain.UnhandledExceptionevent4. Add registry entry to pop up JIT Debugger
5. Use ADPLUS in crash mode with debug symbols installed.
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 _xmlRemoteIs 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.
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.
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.
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" />
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
SessionEndedevent. 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();
}
Most of the desired improvements in this tiny application are down to the bare metal of Windows Forms itself:
System.Windows.Forms.MenuItem needs a proper Icon property. A closer look at Windows Forms 2.0 may reveal an easy way to show menu items in Notification Area with icons. This would make the menus easer to scan.| Resource Location Manager | Download the compiled assembly, the subject of this document. |
| “You Don’t Need a ‘Main’ Form” | This article from Ian Griffiths, co-author of Mastering Visual Studio .NET, provided the fundamental concepts that made this application conceivable. |
| Taskable | The 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 Component” | This article may lead to the next conceptual jump for this kind of application. Maybe not… |
| “Using Resources in Visual Studio .NET” | Dejan 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.” |