Windows 7: Jump Lists

Description

In this article, learn how to provide quick access to links and actions in your Windows 7 application by creating a Jump List.

Introduction

Windows 7 includes a wealth of new features for developers to take advantage of. This includes better rendering subsystems, new sensor and location API's, file libraries, federated search, and of course, the improved taskbar. My last article discussed
the taskbar's ability to show custom previews and toolbar icons. This article focuses on Jump Lists - the replacement for notification area context menus.

What's a Jump List?

Jump Lists are a new concept in Windows 7 that allow developers to provide shortcuts for users right from their icon's context menu in the taskbar or Start menu. The shortcuts could be simple links to the documents folder or a library for a given application,
or links back to the same application with a parameter passed to cause something to happen.

You can use this method in Live Messenger to change online status, display the new message window, or open web pages relating to the application. In the end, all of these are shortcuts. Shortcuts to URL's, or shortcuts back to the executable with an argument
that causes some change to occur.

Windows API Code Pack

The Windows API Code Pack lets you take advantage of specific features of Windows Vista and Windows 7 that aren't available across the general framework, as well as native features that don't make sense in the common CLR used across all the supported configurations.
Much of it consists of interop wrappers.

With the Code Pack, you get access to the new taskbar, Direct2D, DirectWrite, shell properties, Jump Lists, and more. The download also includes numerous sample code projects to get you started, so there's no excuse for avoiding new features!

Adding a Jump List

Adding a Jump List is easy. After you create the list itself, add items (shortcuts to files or folders, and tasks) to it. Then, you can choose how a user's recent or frequently used documents show up. Windows manages the user documents list, which relieves
you of some work.

It's important to note that in order to make a change to the list, you have to recreate the entire thing. In other words, you'll replace the old list with a new one, rather than updating it.

Here's how the process works:

First, add the two required references from the Windows API Code Pack. You can either build a project and reference the DLL's, or directly add projects to your solution:

For convenience, you can add the namespaces to your using block to shorten typing later:

using Microsoft.WindowsAPICodePack.Taskbar;
using Microsoft.WindowsAPICodePack.Shell;

The Microsoft.WindowsAPICodePack.Taskbar.JumpList class is where most of the action is. There's a static factory method,
CreateJumpList, to create the list. Always start by calling this method, even if the application has created a Jump List in the past.

Next, you have several options, depending on what you need in the list. The most basic group is the list of files. You can choose to show Recent files, Frequent files, or neither-but you can't have both. If you don't make a choice here, you'll get Recent
files automatically, as long as you have a registered file type.

Now you can add one or more custom categories of items. These are either folders or files. There are two very important rules:

The files/folders must exist! If necessary, check the path before adding the
JumpListItem or you'll have a crash.

The files you add have to be of a type registered for your application, or you'll crash. Even worse: the exception won't occur on the line where you add it, but rather when you're done setting it up and try to refresh the list.

I've commented out the last item here, but you would use a JumpListItem
for actual file system files, and JumpListLink objects for non-filesystem references. Again, don't add a JumpListItem unless you know that it exists and that you're registered to handle it.

You can add one or more tasks as links to system executables by using the
AddUserTasks method of the JumpList object. Either create multiple objects and add them as a variable argument list, or add them one at a time, as I have here.

The IconReference property sets a pointer to the icon by referencing a DLL or EXE and then an index. Specifying an EXE with "0" is a good way to get the default icon for an executable that you are linking to.

You can add a separator to the list whenever you need to. The JumpListSeparator
class represents a separator and can be added using the AddUserTasks call.

Visual Basic

jl.AddUserTasks(New JumpListSeparator())

Visual C#

jl.AddUserTasks(new JumpListSeparator());

The final links in our Jump List link back to our own executable. This is the most common use of Jump Lists. Just having a Recent/Frequent list is nice, but being able to trigger actions on the program itself-even when it's not started-is really handy.
It's almost like a menu of command line options!

Commands in the list that invoke actions on the application itself involve calling the same application with different arguments. Remember that this isn't a true menu; you won't receive a
Click event. Instead, you need to deal with an argument that's passed to you, even if you're already running.

Remember that the first argument on the command line is always the fully-qualified location to the running executable. The
Arguments property lets you specify command line arguments that users don't directly see. For this sample application, I've defined three dummy arguments. If one of these is passed in, the application changes the background color of a label and indicates
which argument it was.

Invoking Self Actions

Windows Live Messenger uses Jump List actions for setting its own available status, and Windows Media Player has Jump List actions for skipping tracks or stopping. Likewise, you can add tasks that invoke actions on the same executable. If the application
isn't running (remember that the Jump List is still available), this will cause it to be launched with the right argument. That's no problem. What if it's already running though?

The key is to find a way to pass messages between running instances. When the application starts up, check to see if another instance is running by using a
Mutex (see Program.cs). If not, just use the arguments directly. If it is running, send the information about the parameter to the other instance and then quit. You could use temporary files, shared registry keys, or memory-mapped files.
I find it easiest to use window messages.

You can find the code to create custom message ID's, to find the right window, and to send the message in my
WindowsMessageHelper class.

From the main window code, override the WndProc method. This is the message loop for everything: mouse events, key events, window closing, and much more. Ensure that the message is something you need; otherwise pass it on to the underlying handler.

If the application is already running, post a message. If not, start as usual and watch your message queue. If you see a message of interest, take some action (in this case, just showing a message and changing a color).

The only other tricky thing to remember, is that you might startup as the only instance, and
also have a parameter. For example, if the user clicked a task on the Jump List but the application isn't running. I take the easy way out and check for parameters after fully starting up and then post to my own queue if needed! That simplifies
some of the logic anyway.

If you don't mind using the Microsoft.VisualBasic.ApplicationServices namespace from C#, then you can take advantage of the VB SingleInstance application mode. This removes the need for any explicit mutex, interop, or message passing.
You can find some great information about this on Jocelyn Villaraza's excellent
blog post.

Registering a File Type

Remember: unless you're registered as a file handler for the type, you can't show recent or frequent files or point to individual files. Register to be a file handler by creating a registry write operation to a key under HKEY_CLASSES.

The problem is, you can't write to the HKEY_CLASSES branch of the registry without proper permissions. By default, permission is only granted to the Administrators group. You really don't want to require that your application run under administrative privileges-that
would be so Windows XP!

There are two alternatives: you could create a second application that can run elevated in order to perform the registration. This is how the samples do it with the Windows API Code Pack. A better method is to create a custom installer for the project and
perform the association there. Installers always require administrative rights, and they only need to run once.

Creating the Installer

To create the installer, first add a setup project to your solution, following the usual steps. Then, from the
Project types list, click Other Project Types | Setup and Deployment. In the
Templates list, click Setup Project. Give it a name, then add it.

From the File Types list, right-click File Types on Target Machine, and then click
Add File Type. Fill out the properties to name the file type and provide the extension. For
Command, be sure to set it to the Primary output of the main project.

The file type should appear like the following in the File Types
tab:

Now you have a registered file type. You still need to modify your setup project to copy the primary output (the EXE) to Program Files and customize any other properties in the setup project, but these are the special steps for file types. If in doubt,
take a look at sample code to see how the Setup project is configured.

Conclusion

Working with the Windows API Code Pack makes it much easier to customize the taskbar and add Jump Lists, and gives you a great experience that really integrates well with the system. Download Visual Studio Express, grab the Windows API Code Pack, and start
digging in.

The new features won't work on machines prior to Windows 7, so be sure to check that they're supported.

i want the program to launch from the taskbar with the same parameters as it does from the jumplist.

I'm using xml to store Favorites and history, if i launch from the taskbar it uses the xml's in the program folder, however if i launch from the jumplist it uses xml's which have been placed in the System32 folder.

It's all fun and games, but how the heck are we supposed to install that pack? There are virtually no instructions and everything starts from step 11. I'd love to use these shiny features, if I only knew how.

My app is VoIP app so I'd like to have a jumplist that has recent calls and frequent calls, or for simplicity it could be tasks. A "normal" jumplist basically launches an app, in the example below it's a notepad:

In my particular case my app is not executable - it is an Outlook Add-In, so I cannot try to start Outlook again with some kind of parameter - it will not be passed to my add-in by Outlook.

So I either need to write my own little helper app that accepts parameters or use some kind of trick (later about it). The little app would be windowless (but not the service) and carries its own complications, like communicating with my Outlook Add-In securely - using named pipes or similar opens quite a security hole in Outlook - and also seems too laboreous.... The "trick" solution is to use "regedit /s filename.reg" that will get my data into the registry from the reg file that my Outlook Add-in creates, while my add-in will be watching specific registry key. For the latter I will get UAC prompts for every jumplist click (and for now I cannot find how to over this without elevating entire outlook or disabling UAC - not something I want to do... So, basically my question is: is there any way to subscribe to Jumplist_Clicked event (or appropriate event) and get the event plus data in my Outlook Add-In?