C# で Windows 7 のジャンプリストを使ったランチャを作成

Windows 7 に新しく追加された機能「ジャンプリスト」を使ったランチャを作成してみました。とはいっても Windows API Code Pack のデモを改造しただけですが。

本来はタスクバーにゴミ箱を表示するアプリケーションを作ろう!と思っていました。考えた仕様は

  • TrashBox.exe などとして、これをピン留め。
  • ゴミ箱の状態をタイマーで取得してゴミ箱がいっぱいか空かでタスクバーのアイコンを変更。
  • JumpList を使って「ゴミ箱を空にする」コマンドを実行できるようにする。
  • 簡易ランチャ機能とか

といったものでしたがタスクバー アイコンの変更が難しかったのであきらめました。だれか作ってくだしあ><
というわけで以下のコードは簡易ランチャのみの実装です*1コンパイルには Windows API Code Pack 0.85 が必要です。

using System;
using System.Windows.Forms;
using System.Reflection;
using System.IO;
using System.Xml;
using Microsoft.WindowsAPICodePack.Shell;
using Microsoft.WindowsAPICodePack.Shell.Taskbar;
using Microsoft.WindowsAPICodePack;

namespace TaskbarDemo
{
    static class Program
    {
        /// <summary>
        /// The main entry point for the application.
        /// </summary>
        [STAThread]
        static void Main(string[] args)
        {
            if (!CoreHelpers.RunningOnWin7)
            {
                MessageBox.Show("This demo requires to be run on Windows 7", "Demo needs Windows 7", MessageBoxButtons.OK, MessageBoxIcon.Error);
                Application.Exit();
                return;
            }

            string executablePath = Assembly.GetEntryAssembly().Location;
            string executableFolder = Path.GetDirectoryName(executablePath);

            if (args.Length == 0) // 引数がない場合、設定から項目を読み込んで反映させる
            {
                // とりあえずゴミ箱を空にするコマンドを入れてみる。自分を -e オプションで起動
                Taskbar.JumpList.UserTasks.Add(new JumpListLink
                {
                    Title = "ゴミ箱を空にする",
                    Path = executablePath,
                    Arguments = "-e",
                    IconReference = new IconReference("shell32.dll", 31)
                });

                // 設定の読み込み
                XmlDocument doc = new XmlDocument();
                doc.Load(Path.Combine(executableFolder, "config.xml")); // 実行ファイルと同フォルダの config.xml
                XmlElement root = doc.DocumentElement;
                foreach (XmlNode node in root.ChildNodes)
                {
                    string nodeName = node.Name.ToLower();
                    if (nodeName == "link") // 項目を追加
                    {
                        JumpListLink jumpListLink = new JumpListLink();
                        string iconRef = string.Empty;
                        int resourceId = 0;
                        foreach (XmlAttribute attr in node.Attributes)
                        {
                            string attrName = attr.Name.ToLower();
                            if (attrName == "title")
                                jumpListLink.Title = attr.Value;
                            else if (attrName == "path")
                                jumpListLink.Path = attr.Value;
                            else if (attrName == "arguments")
                                jumpListLink.Arguments = attr.Value;
                            else if (attrName == "iconreference")
                                iconRef = attr.Value;
                            else if (attrName == "iconid")
                                resourceId = int.Parse(attr.Value);
                        }

                        if (string.IsNullOrEmpty(iconRef))
                            jumpListLink.IconReference = new IconReference(jumpListLink.Path, resourceId);
                        else
                            jumpListLink.IconReference = new IconReference(iconRef, resourceId);

                        Taskbar.JumpList.UserTasks.Add(jumpListLink);
                    }
                    else if (nodeName == "separator") // 区切りを追加
                    {
                        Taskbar.JumpList.UserTasks.Add(new JumpListSeparator());
                    }
                }

                Taskbar.JumpList.RefreshTaskbarList(); // 反映させる
            }
            else if (args.Length == 1) // 引数がある
            {
                if (args[0] == "-e") // -e ならゴミ箱を空にする
                {
                    RecycleBin.MakeEmpty(); // 自前ヘルパー。SHEmptyRecycleBin を参照されたし
                }
                else if (args[0] == "-c") // -c ならタスクリストをクリア
                {
                    Taskbar.JumpList.RefreshTaskbarList();
                }
            }
        }
    }
}

使い方は引数なしで起動してジャンプリストを更新します。常駐はしません。「ゴミ箱を空にする」コマンドで自分を -e オプションで起動。SHEmptyRecycleBin を呼びます。使わなくなったら一応 -c オプションで起動すればジャンプリストをクリアできる。ところでジャンプリストってどこに保存されるんだろう?
設定ファイルはこんな感じ

<?xml version="1.0" encoding="utf-8" standalone="no"?>
<JumpList>
  <Link Title="DiffBrowser" Path="C:\Applications\DiffBrowser\diffbrowser.exe" Arguments="" IconReference="C:\Applications\DiffBrowser\diffbrowser.exe" IconId="0" />
  <Separator />
  <Link Title="Notepad" Path="%SystemRoot%\notepad.exe" Arguments="" IconReference="%SystemRoot%\notepad.exe" IconId="0" />
  <Link Title="Calc" Path="%SystemRoot%\System32\calc.exe" Arguments="" />
</JumpList>

*1:一応ゴミ箱を空にすることはできる