Driving Sidebar Gadgets with ActiveX and C#

Driving Sidebar Gadgets with ActiveX and C#

he Windows Sidebar is one of the most striking features of the new Vista desktop. It’s a sort of virtual “desktop appliance” which hosts DHTML applets in Windows Explorer. With Vista and its Sidebar, you can enhance the formerly static Windows desktop with myriad widgets and doodads, appropriately named “Gadgets.” By default the Sidebar comes packed with some useful (or maybe just fun) gadgets, such as an RSS streamer, a sticky notepad, a clock/calendar, a CPU meter, and one of those ‘slide the tile’ games where you try to make the complete picture?but who needs another one of those?

Why the SideBar? Why Now?
You might ask why Microsoft has bothered to raise the Sidebar to desktop prominence in Vista?after all, isn’t that what the Office Suite and Start menu are for? Well yes, but the Sidebar has more features. For example, you can hide the Sidebar, or float it somewhat transparently over other apps. It’s convenient, because it makes commonly-used applications easy to find, and it’s easily recallable from a hidden state by clicking a tiny icon in the system tray. Another purpose of the Sidebar is to “look pretty!” That’s no joke?it’s in the documentation. And as long as people who are more artistic than I am are writing the majority of gadgets, I do believe that will remain a primary reason for the Sidebar’s existence.

Author’s Note: Vista was still in RTM at the time of this writing, so there is little “user provided” documentation on the subject.

What’s in a Gadget?
A gadget is a DHTML applet. These applets consist of HTML (the user interface), JavaScript (interactivity), and other web content files. Gadgets are almost exactly like any other DHTML applet that you’d host in Internet Explorer, except that they are packaged slightly differently, and have a special API extension available to allow them to integrate with or “plug-in” to the hosting system.

You can store gadget files wherever you like in the file system?with one caveat: The top-level folder must be named .gadget, where is a name of your choice.

Every gadget has an XML file that contains a manifest file. The manifest is a simple XML file containing information that describes the gadget and its parts to the host. The gadget manifest must be named gadget.xml and reside directly within the .gadget folder. Here’s an example gadget manifest.

  QuickMailr          2007  Email a tiny bit of text using an Active X       control written in C#!                  Full              

The elements of a gadget manifest file are similar for all gadgets. All gadget manifests contain standard elements such as the name, version, author, and src attributes under the gadget element. The name and version elements are self explanatory. The author element lets you give yourself credit (or blame) for the gadget, and the optional info element under it lets you provide a website link. The hosts element is there so you can specify a hosting application; although at the present time, there is only one available host?the Sidebar, which you specify in the manifest in lowercase letters as in the preceding example. The permissions element theoretically allows you to vary the rights afforded your gadget, but for the time being you must use Full (which turns out to be quite a lot of permissions).

The QuickMailr Gadget
The example gadget described in this article is called QuickMailr, which lets you email yourself or someone you know a link or a short text message?without having to open your email application. It has two text boxes: an address field into which users enter the “To” address, and a message field into which users paste a link or a short text message (see Figure 1).

Figure 1. QuickMailr Gadget: The figure shows the QuickMailr gadget running in the Windows Sidebar.

You can download the full source code for this gadget to follow along with the rest of this article.Technically, you could paste an entire novel into the message field?I didn’t limit the input size?but as written, it would be a bit painstaking to try to proofread before sending, because the display area is so small. Microsoft recommends that gadgets should be no larger than 130 x 200 pixels. This helps keep them handy, while still allowing room for other gadgets. The gadget API doesn’t expose any innate ability to send email, so I had to write an ActiveX control to take care of that part.

When I say ActiveX, you might think I mean ATL and C++. Fortunately for those who have been spoiled by the straightforward, garbage-collected, managed code environment of the Common Language Runtime, you can do this in plain old C# by taking advantage of COM Interop to leverage a .NET component as a COM-visible entity. Rather than trying to explain the gory details (though that’s not to say they aren’t important to understand), I’ll just present an example that all but eliminates the need to consider exactly how the Interop process works.

A Consistent Platform
A key point is that the Sidebar provides a consistent platform host for DHTML applets. Unlike web-delivered applets, you won’t have to write different versions or test for different conditions to support a variety of platforms. The Sidebar treats script and HTML exactly as Internet Explorer (IE) would; in other words, all the features available to IE, including ActiveX, are available to gadgets. I’m going to defer showing the ActiveX control implementation for the moment, but I’ll come back to it later.

HTML Files
After the manifest, the next most prominent feature of a gadget is the HTML file itself. It bears the file name that is specified in the manifest, (gadget.html in this example.) The main “form” is a normal HTML file, with all the trimmings you desire, including CSS, JScript (or VBScript), and media files. The incorporation of both common old ASP classic script dialects?VBScript and JScript (the Microsoft extended version of Javascript)?will be a welcome addition for some of the more nostalgic developers.

The HTML itself is really nothing special. In my example I’ve embedded the Javascript directly into the HTML file between

The last fully new feature, which you've just seen a peek of, is the System.Gadget and other related API enhancements available from the Sidebar environment. You don't have to do anything out of the ordinary to use the API; the host makes it directly available to your scripts without you having to specify any include files or link any external libraries. The Gadget API has methods that allow you to work with CardSpace contacts, hardware statistics, and performance data as well as a way to persist your gadget's particular settings to an INI file.

Persisting Settings
The other interesting bit of the example gadget is the persistent settings. The System.Gadget.Settings class has four methods that allow you to store your gadget specifics. That's not quite as great as it sounds, because the data disappears as soon as you remove your particular instance of the gadget from the host (when you close it). At one level, that makes sense, because theoretically you could have multiple instances of the same type gadget, and you wouldn't want them fighting with each other over settings storage. But when you make only one instance of your gadget available, having persistent settings makes sense.

Here's a snippet that will store settings read from a form field using the API:

   // From settings.html in the downloadable code.    function SaveSettings()   {      System.Gadget.Settings.writeString("SMTPServer",             SMTPServer.value);      System.Gadget.Settings.writeString("SMTPPort",         SMTPPort.value);      System.Gadget.Settings.writeString("SMTPUser",          SMTPUser.value);      System.Gadget.Settings.writeString("SMTPPassword",          SMTPPass.value);      System.Gadget.Settings.writeString("FromAddy",             FromAddy.value);   }

Here you can spot another "feature" of the native Microsoft version of scripting. I can refer to defined HTML form fields using standard (X)HTML as if they were objects. There is no need to repeatedly use document.getElementByID in this environment. If you write your script in Visual Studio or Visual Web Developer, you'll notice that Intellisense kicks in when you enter the name of an element on the page, and auto-completes as if you had declared the elements as actual objects. Reading the values back into the form is also a snap, as shown below.

   // From settings.html   function PopulateSettings()   {        SMTPServer.value = System.Gadget.Settings.readString("SMTPServer");      SMTPPort.value = System.Gadget.Settings.readString("SMTPPort");      SMTPUser.value = System.Gadget.Settings.readString("SMTPUser");      SMTPPass.value = System.Gadget.Settings.readString("SMTPPassword");      FromAddy.value = System.Gadget.Settings.readString("FromAddy");               }

So you've had a quick glance at the underpinnings of gadgets and the Sidebar; now it's time for you to see one in action. You can accomplish many things with only normal script and HTML, especially when you add in the gadget API; however, you can do even more by writing an ActiveX control and using that to do any additional heavy (and possibly privileged) lifting that you can't accomplish with simple script.

Building the ActiveX Control
The ActiveX control for this example is a simple one-method class that does nothing but send an email message via SMTP. The content, subject, format, and SMTP settings are all encapsulated in the parameters of the single method, which minimizes the interface footprint. Listing 1 shows the entire source for the object:

The code in Listing 1 simply invokes the built in System.Net.SmtpServer class to send an email represented within a System.Net.Mail.MailMessage. It's a relatively trivial operation using the Microsoft .NET Framework version 2.0, but two things make the component COM-worthy after compilation:

  1. The inclusion of ComVisible(true) in the AssemblyInfo.cs file
  2. The code is signed with a strong name. This isn't really a hard requirement, but it sidesteps some issues that sometimes pop up when exposing .NET components as ComVisible, (namely, the component can be installed into the Global Assembly Cache.)

After building the project, copy the DLL from the output directory to somewhere where it is safe to register. I located it in the gadget directory, which for the sake of the example is named QuickMailr.gadget.

Registering the DLL
After compiling, you need to register the DLL for COM. You'll need administrator privileges to register it. One Vista feature is User Account Control (UAC), which allows administrators to run most processes with normal user (non-admin) privileges. This means that you have to elevate your permissions to register the library using the standard RegAsm.exe tool. UAC isn't a show-stopper at all?you just need to invoke the command shell as an administrator. Here's the step-by-step procedure to register the DLL:

  1. Right click on the Visual Studio Command Prompt in the Start Menu, or the C:WindowsSystem32cmd.exe icon in Windows Explorer and select "Run As Administrator." A normal-looking command shell window will appear.
  2. From the command prompt, change directory (cd) to the directory where you placed the compiled DLL file.
  3. Enter RegAsm.exe /codebase NameOfYourDll.exe

Assuming you named your DLL ActiveXMailer, for this example, the command line for step #3 would be:

   RegAsm.exe /codebase ActiveXMailer.dll
Author's Note: The included Install.cmd file contains that line of script; you can simply right click on the file and choose "Run As Administrator" to perform the registration, provided that the RegAsm.exe executable (from the .NET Framework version 2.0 SDK) is in your path. If it's not in your path, you can invoke the Install.cmd file from a Visual Studio Command Prompt.

If you see the standard success message, "Types registered successfully," the DLL is registered properly, and you can close the command shell.

Installing the Gadget

Figure 3. Configuring the Gadget: You access the settings by clicking on the small "wrench" settings icon.

I mentioned earlier that Sidebar gadgets must reside in folders with names that end in .gadget, but you can also package them as CAB or ZIP archives. The easiest method is to take the .gadget folder (QuickMailr.gadget in this case) and zip it using the "Send To? Zip Archive" option in the Windows Explorer context menu. After the .zip file is created, rename the file by replacing .zip with .gadget. This tells Windows that the files contained within the archive are a Sidebar gadget.

After zipping and renaming the gadget file, you can install it by simply double clicking on the file icon. A prompt will appear asking if you'd like to install the gadget. Choosing "Install" will publish the gadget and extract the contents to a folder (%userprofiledir%AppDataLocalMicrosoftWindows SidebarGadgetsQuickMailr.gadget). To add your gadget to the Sidebar, right click anywhere on the Sidebar background and select "Add Gadgets?"

If all has gone according to plan, the new gadget will appear in the list, and you can select it using a double click.

That's it! The gadget is up and running and should look like Figure 1. All that's left to do is configure the SMTP settings. If you hover your mouse over the gadget in the Sidebar, a small 'wrench' icon appears next to it (see Figure 3).

The "settings" icon is a standard feature of all gadgets that support a settings panel. Click the settings icon and enter your SMTP information as shown in Figure 4.

Figure 4. QuickMailr Settings: Here's the QuickMailr settings panel, where users enter their SMTP information so they can send email messages.

After closing the settings panel, you're now ready to send some QuickMail! Just enter one of your own email addresses in the TO: field, and paste your favorite link (e.g. into the Message field, and click "Send." Seconds later, you'll get an email with the subject "QuickMailr Message."

The concept of the Sidebar is relatively familiar, but it does provide a consistent and useful host for DHTML applets that can enhance the overall Vista experience. There are many more avenues to explore in the realm of building Sidebar gadgets, and I highly recommend that you peruse the official Microsoft documentation.


Share the Post: