User Tasks
User tasks despite their name are additional tasks that can be placed in your application’s
Jump List. These are verbs that can invoke your application or any other application, and
they’re usually r
User tasks despite their name are additional tasks that can be placed in your application’s
Jump List. These are verbs that can invoke your application or any other application, and
they’re usually represented by IShellLink objects. After you’ve mastered the intricate details of
adding categorized destinations to the Jump List, user tasks are much easier to grasp.
Note Because user tasks are not connected to an existing application instance, it makes sense to
set them up during application installation. To do this, you can either ensure that your installer has
the same AppID as the application itself, or you can launch an auxiliary application from within the
installer that claims the same AppID and creates the user tasks. (This auxiliary application could
also be your main application with a “quiet-mode” switch that creates the tasks and exits without
displaying UI.)
You need the ICustomDestinationList interface if you’re working from native code. After
beginning a list-building transaction (with BeginList), you can use the AddUserTasks method
to add a collection of tasks usually represented by an IObjectCollection containing
IShellLink objects.
As you might remember, the task list can contain separators that group related tasks. To add a
separator, create an IShellLink object and use the IPropertyStore interface to set its
System.AppUserModel.IsDestListSeparator property to TRUE. This object can then be added to
the Jump List along with the rest of the tasks.
The managed equivalent for adding user tasks is the JumpList.AddUserTasks method, which
accepts JumpListLink, JumpListItem, and JumpListSeparator objects and adds them to the underlying tasks collection. The following code snippet, which displays both the native and
managed code, demonstrates how to add a few user tasks to the application’s Jump List:
//C++:
ICustomDestinationList* pJumpList = NULL;
if (FAILED(CoCreateInstance(
CLSID_DestinationList, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&pJumpList))))
goto Cleanup;
if (FAILED(pJumpList->SetAppID(L"Microsoft.Samples.MyApplication")))
goto Cleanup;
UINT uMaxSlots;
IObjectArray* pRemoved = NULL;
if (FAILED(pJumpList->BeginList(&uMaxSlots, IID_PPV_ARGS(&pRemoved))))
goto Cleanup;
IObjectCollection* pContents = NULL;
if (FAILED(CoCreateInstance(
CLSID_EnumerableObjectCollection, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&pContents))))
goto Cleanup;
IShellLink* pLink = NULL;
IPropertyStore* pStore = NULL;
PROPVARIANT var;
//Create a simple link to calc.exe:
if (FAILED(CoCreateInstance(CLSID_ShellLink, NULL,
CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&pLink))))
goto Cleanup;
if (FAILED(pLink->SetPath(L"C:\\Windows 7\\System32\\calc.exe")))
goto Cleanup;
if (FAILED(pLink->QueryInterface(IID_PPV_ARGS(&pStore))))
goto Cleanup;
InitPropVariantFromString(L"Launch Calculator", &var);
if (FAILED(pStore->SetValue(PKEY_Title, var)))
goto Cleanup;
if (FAILED(pStore->Commit()))
goto Cleanup;
if (FAILED(pContents->AddObject(pLink)))
goto Cleanup;
pStore->Release(); pStore = NULL;
pLink->Release(); pLink = NULL;
//Create a separator link:
if (FAILED(CoCreateInstance(CLSID_ShellLink, NULL,
CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&pLink))))
goto Cleanup;
if (FAILED(pLink->QueryInterface(IID_PPV_ARGS(&pStore))))
goto Cleanup;
InitPropVariantFromBoolean(TRUE, &var);
if (FAILED(pStore->SetValue(PKEY_AppUserModel_IsDestListSeparator, var)))
goto Cleanup;
if (FAILED(pStore->Commit()))
goto Cleanup;
if (FAILED(pContents->AddObject(pLink)))
goto Cleanup;
//Create a simple link to notepad.exe:
if (FAILED(CoCreateInstance(CLSID_ShellLink, NULL,
CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&pLink))))
goto Cleanup;
if (FAILED(pLink->SetPath(L"C:\\Windows 7\\System32\\notepad.exe")))
goto Cleanup;
if (FAILED(pLink->QueryInterface(IID_PPV_ARGS(&pStore))))
goto Cleanup;
InitPropVariantFromString(L"Launch Notepad", &var);
if (FAILED(pStore->SetValue(PKEY_Title, var)))
goto Cleanup;
if (FAILED(pStore->Commit()))
goto Cleanup;
if (FAILED(pContents->AddObject(pLink)))
goto Cleanup;
IObjectArray* pContentsArr = NULL;
if (FAILED(pContents->QueryInterface(IID_PPV_ARGS(&pContentsArr))))
goto Cleanup;
if (FAILED(pJumpList->AddUserTasks(pContentsArr)))
goto Cleanup;
pJumpList->CommitList();
Cleanup:
if (pLink != NULL)
pLink->Release();
if (pStore != NULL)
pStore->Release();
if (pContentsArr != NULL)
pContentsArr->Release();
if (pContents != NULL)
pContents->Release();
if (pRemoved != NULL)
pRemoved->Release();
if (pJumpList != NULL)
pJumpList->Release();
//C#:
JumpList jumpList = JumpList.CreateJumpList();
jumpList.AddUserTasks(
new JumpListLink(@"C:\Windows 7\System32\Calc.exe", "Launch Calculator"),
new JumpListSeparator(),
new JumpListLink(@"C:\Windows 7\System32\Notepad.exe", "Launch Notepad"));
jumpList.Refresh();
Unlike custom destinations, tasks cannot be removed from the Jump List by the user, nor can
they be pinned to the list. Tasks receive an additional preference when there’s not enough room in the Jump List they are trimmed last so that only the space that remains after
displaying all user tasks can be used by the rest of the Jump List categories.
Users expect the user tasks area of the Jump List to remain static. The state of the
application should not affect the list of user tasks, especially because the application might shut
down unexpectedly, leaving the Jump List in an undesired state. Nonetheless, there are some
applications including Windows 7 Live Messenger that use contextual user tasks, such as Sign In
and Sign Out, with great success. |