Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / web / HTML

Inside Vista Sidebar

4.70/5 (16 votes)
8 Mar 2008CPOL10 min read 1  
An insider look at the Vista Sidebar. Learn how the Sidebar works and how to optimize your Gadgets development.

Introduction

Vista Sidebar Gadget allows you to bring on the Vista desktop all sorts of information you need: RSS feed, weather, stock value... You can easily write your own gadget with a little HTML and JavaScript code. However, because of lack of a development environment, writing a gadget could be somewhat frustrating. Sometimes you don't know why your gadget doesn't work as you want it to. Writing this article, I've decided to explore how the Vista Sidebar works internally so I could have a better understanding of some debugging issues. Follow me on the dark side of the Vista Sidebar!

What is the Sidebar?

What is the Vista Sidebar? A single definition could be: "The Vista Sidebar is a part of the Vista desktop where you can drag small apps called Gadgets." In a sense it's true but the Sidebar is not really "a part of the Vista desktop". Let’s try that: minimize one by one all Windows on your desktop to let only the Sidebar show. Now, click on the "show desktop" icon in the menu bar. What happens? The Sidebar is minimized! It’s incredible, isn't it? In my opinion, it’s a bug: when you use this icon to minimize all Windows, it's probably because you need to have only the desktop, so you could hope to see the Sidebar too. Now a stranger feature: reopen any window that you've previously minimized: both your window AND the Sidebar are now visible! In my opinion, it's just a hack that Microsoft’s developers have found to solve the "minimized Sidebar bug".

So, what is the Sidebar? The Sidebar is a window application like any other. It's why the Sidebar is affected too by the "minimize all Windows" icon. The EXE for this application is in %ProgramFiles%\Windows Sidebar\sidebar.exe. Two instances of this process are always launched for the purpose of isolation: The first one hosts the preinstalled gadgets (clock, weather, calendar, stocks, and so on), while the second hosts all user-created gadgets. You can see both processes with Process Explorer by Mark Russinovich.

Sidebar processes in Process Explorer - Click for full size image

Try to kill the descendant process: all your downloaded gadgets will disappear; try to kill the root process: all the Sidebars will disappear.

Hosting Gadget

To write your own gadget, you just have to write an HTML page and some JavaScript source code. To host a gadget, the Sidebar uses Internet Explorer. More precisely, the Sidebar uses the ActiveX Component MSHTML.DLL. MSHTML.DLL control allows you to host an Internet Explorer instance and have a very fine control on various aspects of the browser behavior and appearance. The Sidebar creates one instance of the ActiveX control for each gadget. You can check that point using the Visual Studio Tools Spy++. Use the search window option in the menu and click on a Gadget to see all properties. You could also use Process Explorer again: right-click on sidebar.exe and on the Threads tabs, you'll find multiple instances of MSHTML.DLL.

Using Spy++ to track Gadgets hosting - Click for full size image

When your Gadget makes an HTTP request to an external server, the USER_AGENT value is the same as with Internet Explorer 7 and the REFERER value is the name of the current Gadget page prefixed by x-gadget:///. Because Gadgets are hosted in Internet Explorer, a common problem in debugging Gadgets involves caching. For both images included in your HTML or for HTTP requests in your scripts, don't forget that IE uses its cache first. So to avoid caching problems, you need to change the HTTP Expires header or add a timestamp behind all your requests.

Sidebar API

The Sidebar API is a JavaScript API that you can use in your Gadget to implement some specific behavior (flying out, window settings, and the like) or to access some system information (CPU, power status, network settings). The Sidebar API includes properties, methods, and events, all of which are callable with the System prefix. For example, here is a call of the Sidebar API to print debug information on CPU use:

JavaScript
System.Debug.outputString("CPU usage is " + System.Machine.CPU.usagePercentage);

To give you access to this API, Sidebar processes use a feature of the MSHTML.DLL control to expose application-specific functions to JavaScript. More precisely, all exposed properties, methods, and events of the Sidebar API are exposed as COM interfaces hosted by the Sidebar process. To illustrate, I use the OLE/COM Object Viewer tools from Microsoft to explore the Type Library inside sidebar.exe. Launch OLEVIEW, click on File/View TypeLib… menu and open sidebar.exe. Here is a part of the resulting IDL that you get. You can see both APIs used in the previous sample.

JavaScript
// Generated .IDL file (by the OLE/COM Object Viewer)
//
// typelib filename: sidebar.exe

[
  uuid(AAA49BB1-378C-4206-9CAD-53C3372E9550),
  version(1.0),
  helpstring("Microsoft Sidebar API Type Library")
]
library Sidebar
{
    // TLib :     // TLib : OLE Automation : {00020430-0000-0000-C000-000000000046}
    importlib("stdole2.tlb");

    // Forward declare all types defined in this typelib
    interface ISettings;
    interface IGenericCollection;
    dispinterface DispSettings;
    interface IEnvironment;
    dispinterface DispEnvironment;
    interface ISystemMachinePowerStatus;
    interface ISystemMachinePowerStatusBatteryStatus;
    interface ISystemMachineCPU;
    interface ISystemMachine;

    ...

    [
      odl,
      uuid(B68EEF74-E7F5-4CED-B214-B8BE05C79E3F),
      dual,
      nonextensible,
      oleautomation
    ]
    interface ISystemMachineCPU : IDispatch {
        [id(0x000075f9), propget]
        HRESULT name([out, retval] BSTR* pCpuName);
        [id(0x000075fa), propget]
        HRESULT usagePercentage([out, retval] single* pUsagePercentage);
    };

    ...


    [
      odl,
      uuid(746B224A-6E2A-4A43-A5C6-D10717C910B4),
      dual,
      nonextensible,
      oleautomation
    ]
    interface ISystemDebug : IDispatch {
        [id(0x00001068)]
        HRESULT outputString([in] BSTR psz);
    };

    ...
}

The following figure sums up the overall architecture of Sidebar and the use of Windows Live Services ActiveX that we'll see below:

Sidebar overall architecture

One commonly used feature in the Sidebar API is System.Gadget.Settings, with methods such as read, readString, write, and writeString that let your Gadget load and save its settings when users open/close the settings window. Since I'm always wondering where these settings are stored, I used another great tool by Mark Russinovich - Process Monitor - to find the answer. I launched it before changing the settings of a Gadget. Here is the result:

Process Monitor tool on Sidebar - Click for full size image

It appeared that all Gadget settings are stored in a unique INI file named %USERPROFILE%\AppData\Local\Micros oft\Windows Sidebar\Settings.ini. Each Gadget instance had its own section in this file. The following code shows the section for a Weather Gadget in Settings.ini.

JavaScript
...
[Section 4]
PrivateSetting_GadgetName=
    "C:%5CProgram%20Files%5CWindows%20Sidebar%5CGadgets%5CWeather.Gadget"
PrivateSetting_Enabled="true"
PrivateSetting_SidebarDockedState="Docked"
PrivateSetting_GadgetTopmost="false"
WeatherLocation="Saint-Quentin-en-Yvelines,%20Yvelines"
WeatherLocationCode="wc:FRXX0280"
DisplayDegreesIn="Celsius"
PrivateSetting_GadgetDropLocationX="1051"
PrivateSetting_GadgetDropLocationY="387"
PrivateSetting_GadgetOpacity="100"
...

Though it's not good practice, you can manually change settings into this file instead of using the Sidebar API.

Gadget Source Code

Because Gadgets are only HTML and JavaScript, everyone can see their source code. Each user Gadget is installed in a subdirectory of %USERPROFILE%\AppData\Local\Microsoft\Windows Sidebar\Gadgets. The subdirectory’s name is the name of the gadget optionally followed by a number if you've got more than one instance of the same Gadget in the Sidebar.

Vista standard Gadgets (clock, weather, calendar, stocks, and the like) are located in another directory %ProgramFiles%\Windows Sidebar\Gadgets. Three of these gadgets—weather, stocks, and currency—have another particularity: Their source code uses an ActiveX Control called WLSRVC (short for “Windows Live Service ActiveX”) that's embedded in the Sidebar directory. Here again, you can use OLE/COM Object Viewer tools to see its interface, click on File/View TypeLib... menu and open wlsrvc.dll. Following is a part of the resulting IDL:

JavaScript
// Generated .IDL file (by the OLE/COM Object Viewer)
//
// typelib filename: wlsrvc.dll

[
  uuid(4F47FCF0-E864-4D97-B309-2F5902306128),
  version(1.0),
  helpstring("Windows Live Services 1.0 Type Library")
]
library wlsrvcLib
{
    // TLib :     // TLib : OLE Automation : {00020430-0000-0000-C000-000000000046}
    importlib("stdole2.tlb");

    // Forward declare all types defined in this typelib
    interface IWLForecast;
    interface IWLWeather;
    interface IWLServiceData;
    interface IWLWeatherService;
    interface IWLStock;
    interface IWLStockService;
    interface IWLCurrency;
    interface IWLCurrencyData;
    interface IWLCurrencyService;
    interface IWLServices;

    ...
    [
      odl,
      uuid(3E46F4F0-D6FE-49E4-97E5-C731154F4E7A),
      helpstring("IWLServices Interface"),
      dual,
      nonextensible,
      oleautomation
    ]
    interface IWLServices : IDispatch {
        [id(0x00000001), propget]
        HRESULT GetService(
                        [in] BSTR bstrServiceName,
                        [out, retval] IDispatch** ppDisp);
    };
    ...
}

Below is a part of the source code of the Vista Weather Gadget. You can see the creation and use of the WLSRVC ActiveX.

JavaScript
...

////////////////////////////////////////////////////////////////////////////////
//
// WeatherGadget() - main Constructor
//
////////////////////////////////////////////////////////////////////////////////
function WeatherGadget()
{
  var self = this;

  ...
  try
  {
    // Connect to Weather Service .dll
    var oMSN = new ActiveXObject("wlsrvc.WLServices");
    this.oMSN = oMSN.GetService("weather");
  }
  catch (objException)
  {
    this.isValid = false;
    this.statusMessage = getLocalizedString('ServiceNotAvailable');
    this.oMSN = new Object();
  }

  ...

I'm not sure whether Microsoft chooses this architecture for performance reasons or to avoid exposing the source code handling Windows Live services.

Finally, the %ProgramFiles%\Windows Sidebar\Shared Gadgets directory holds Gadgets installed by system administrators for corporate deployment of Gadgets. Consequently, it's possible to restrict users to only install corporate Gadgets or to forbid users from installing new ones.

Localized Files

One of coolest features of Gadgets is their support for localization. For each file packaged in your Gadget (*.html, *.jpg, *.js, and the like), you can provide a corresponding file for each language you need to support. Selection of the right file is done transparently by the Sidebar — you just need to put your file in a subdirectory corresponding to your local or regional code (as with .NET assemblies).

We can see this feature at work again using the Process Monitor:

Process Monitor tool on Sidebar - Click for full size image

Here, my Gadget calls a HelloWorld.html page. Though this page is in the root folder, the Sidebar process first looks for this file in the regional folder (“fr-FR” for France) then in the local folder (“fr” for French). Because both calls result to a path not found error, the process then gets the file in the root folder.

Translating a URL is a feature of the MSHTML ActiveX Component. Using interface IDocHostUIHandler::TranslateUrl, you can intercept all URLs called in the hosted HTML page before the navigation start. Though there is no evidence about this, it's probably this feature that the Sidebar uses to catch all URLs called in your Gadget. Each relative's URL is then translated to a localized equivalent when possible. Have a look at the MSDN Library to learn more about IDocHostUIHandler interface and the TranslateUrl feature.

Security

Internet Explorer lets you configure security settings depending on which Web sites you visit. Gadgets always run in Local Machine Zones as if they are HTML local applications. Gadgets are allowed to create or embed ActiveX controls but these controls should be present on the machine. Note also that embedded ActiveX controls are restricted by the Vista User Access Control (UAC). Moreover, the Sidebar never displays the UAC elevation prompt.

Instead of a traditional Web page, Gadgets could access data from multiple domains and multiple servers without restriction. An interesting feature is that when a Gadget calls an HTTP request, it could rely on NT Authentication so you can call a corporate Web service that needs to check the membership of the user from an NT group.

Debugging Gadgets

To debug Gadgets, you need to use Visual Studio and attach it to sidebar.exe (use the Debug/Attach to process... menu item). This attachment lets you catch JavaScript errors and set breakpoints in your source code. Unfortunately, in my experience as a Gadget developer since Vista RC1, debugging Gadgets works randomly. Attachments to Visual Studio let you also use an “old style” debugging: “print”! Again, you can use System.Debug.outputString to display debug information in the output window of Visual Studio.

Gadget Development Environment

Working on Gadget development for months, I have a dream: a dream that Microsoft provides us a great development environment for Gadgets. An IDE where I wish you could easily host your Gadget in Visual Studio, hook API calls, and emulate features like settings, flyout and undocked view. With this IDE, I wish you could always debug code, catch errors and dynamically add JavaScript code. Of course, I wish you could also use this IDE to debug non Gadget AJAX apps.

This dream doesn't come true with Visual Studio 2008 but Visual Studio 2008 goes forward in the right direction. One of the more useful Visual Studio 2008 features is JavaScript Intellisense, an automated autocompletion technology that speeds up development by reducing the amount of JavaScript code you have to write. See Figure below to see Intellisense at work in Visual Studio 2008.

Intellisense in Visual Studio 2008 - Click for full size image

Because JavaScript can be difficult to code, JavaScript IntelliSense is most helpful when writing standard JavaScript code and ASP.NET AJAX client-side code. JavaScript doesn't have explicit type declaration because it is a dynamic language. Visual Studio, on the other hand, uses “type inference” to detect the current type of any variable and give you the right suggestion in your current context. Because developing, say, a Vista Sidebar Gadget produces lots of JavaScript code, Intellisense is a really useful feature. Moreover, Visual Studio 2008 lets you provide help information on JavaScript code using C# comment template (///). Consequently, the Intellisense’s tooltip can display description for functions and parameters.

A good place to have Intellisense is on the SideBar API. Unfortunately, because the SideBar API is a COM interface, Visual Studio type inference doesn't detect it. To avoid this drawback, I wrote a dummy JavaScript file matching the SideBar API interface. I include it at design time only to get Intellisense on the SideBar API. The listing below shows the functions used in the first example I present.

JavaScript
///////////////////////////////////////////////////////////////////////////
// Dummy SideBar API
// Match System.* interface to provide help information on Intellisense
///////////////////////////////////////////////////////////////////////////

var System = new SystemClass();

function outputString(strOutputString) {
/// <summary>Writes a string to the console.</summary>
/// <param name="strOutputString">Required. String to write to the console.</param>
    alert(msg);
}

function DebugClass() {
/// <summary>Defines the method available for debugging Windows Sidebar gadget script
    </summary>
    this.outputString = outputString;
}

function MachineClass() {
/// <summary>Gets the percentage of a microprocessor's capacity being used.</summary>
    this.usagePercentage = 100;
}

function SystemClass() {
    this.Debug = new DebugClass();
    this.Machine = new MachineClass();
}

A good practice when developing Gadgets is to first develop all source code in a single HTML page and run your page in Internet Explorer so you can debug easily out of sidebar.exe, in Visual Studio IDE. When all your features work correctly in HTML, you'll mix it with graphics and Gadget specific code in a packaged Gadget. Another option is to use a JavaScript-only SideBar Framework like the one shown before. Using this kind of hack, you could imagine writing something like a SideBar emulator to fully test your gadget in Visual Studio. I hope some of you will attempt to go on this adventure.

Conclusion

Until waiting for a magic IDE, Gadget development is a complex job. Visual Studio 2008 provides us some nice features but lacks a Gadget template project and an emulator mode. I hope that the internal hacks and tips I showed here help you to be more productive and have a better understanding of the way in which the Vista SideBar works.

Acknowledgment

Thanks to Smaïl Aïssaoui for his thorough reading of this article.

History

  • 8th March, 2008: Article posted

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)