LoginSignup
38

More than 5 years have passed since last update.

.NET で Windows エクスプローラのコンテキストメニューを拡張

Last updated at Posted at 2016-09-04

はじめに

僕は以前 Delphi で Windows のシェル拡張(Shell Extension)を使っでエクスプローラに機能を追加するアプリを作りました。
簡単エクスプローラ拡張 EzExpEx
これは残念なことに 64 ビット Windows のエクスプローラで動かないんですよね。僕が持っている Delphi では 64 ビット Windows アプリを作れないんです。
これを VB.NET で作り直したいとずっと思っていました。

そのために調べていると次の記事がありました。
.NET Shell Extensions - Shell Context Menus - CodeProject
これは C# で書かれています。
このまま使ってもいいのですが、僕は VB が好きなので移植することにしました。

Windows シェル拡張でコンテキストメニュー

エクスプローラで右クリックするとコンテキストメニューが表示されます。このメニューに独自の項目を追加します。

プロジェクトを作る

まず、「クラスライブラリ」のプロジェクトを新規作成します。

ここではプロジェクト名を「ContextMenuExtension」にします。* 元記事と違います。

次に、プロジェクトの「参照」設定に以下のアセンブリを追加します。

  • System.Windows.Forms
  • System.Drawing

IDE が作成したソースファイル「Class1.cs」または「Class1.vb」を「ContextMenuExtension.cs」または「ContextMenuExtension.vb」にリネームします。* 好きなファイル名で構いません。

SharpShell ライブラリを使う

「SharpShell」ライブラリを使います。

以下のページで配布されています。
SharpShell - CodePlex

「SharpShel.dll」を使います。これをプロジェクトの「参照」に追加します。

これを手作業してもいいけれど、Nuget を使うのが楽です。

SharpContextMenu から派生する

「ContextMenuExtension」クラスを「SharpContextMenu」から派生するよう書換します。

ContextMenuExtension.cs
public class ContextMenuExtension : SharpContextMenu
{
ContextMenuExtension.vb
Public Class ContextMenuExtension
    Inherits SharpContextMenu

IDE が「抽象クラスの実装」を助言してくるので従って以下のメソッドを実装します。

  • CanShowMenu
  • CreateMenu
ContextMenuExtension.cs
    protected override bool CanShowMenu()
    {
        // 常に表示する
        return true;
    }

    protected override ContextMenuStrip CreateMenu()
    {
        // メニューを生成して項目を追加する
        var menu = new ContextMenuStrip();
        var item = new ToolStripMenuItem
        {
            Text = "行数をカウント"
        };
        item.Click += (sender, args) => CountLines();
        menu.Items.Add(item);
        // メニューを返す
        return menu;
    }
ContextMenuExtension.vb
    Protected Overrides Function CanShowMenu() As Boolean
        '常に表示する
        Return True
    End Function

    Protected Overrides Function CreateMenu() As ContextMenuStrip
        'メニューを生成して項目を追加する
        Dim menu As New ContextMenuStrip
        Dim item As New ToolStripMenuItem(text:="行数をカウント")
        AddHandler item.Click, New EventHandler(AddressOf CountLines)
        menu.Items.Add(item)
        'メニューを返す
        Return menu
    End Function

主な機能は「CountLines」。選択したファイルの名称と行数を表示します。

ContextMenuExtension.cs
    private void CountLines()
    {
        var builder = new StringBuilder();
        foreach (var path in SelectedItemPath)
        {
            builder.AppendLine(string.Format("{0} - {1} 行", IO.Path.GetFileName(path), IO.File.ReadAllLines(path).Length));
        }
        // メッセージボックスで表示する
        MessageBox.Show(builder.ToString());
    }
ContextMenuExtension.vb
    Private Sub CountLines()
        Dim builder As New StringBuilder  
        For Each path In SelectedItemPaths
            builder.AppendLine(String.Format("{0} - {1} 行", Path.GetFileName(path), File.ReadAllLines(path).Length))
        Next
        'メッセージボックスで表示する
        MessageBox.Show(builder.ToString)
    End Sub

SharpContextMenu クラスの SelectedItemPaths で、エクスプローラで選択したファイルを取得できます。

COM サーバ登録機能を実装する

作成しているクラスライブラリが COM サーバとして登録できるようにします。

まず、アセンブリを COM 参照可能にします。以下の手順で作業します。* 元記事にないようです。

プロジェクトの「プロパティ」を開く。
「アプリケーション」タブを選択。
「アセンブリ情報」を押下。
ダイアログボックスで「アセンブリを COM 参照可能にする」にチェック。

次に、アセンブリに署名します。以下の手順で作業します。

プロジェクトの「プロパティ」を開く。
「署名」タブを選択。
「アセンブリに署名する」をチェック。
「厳密な名前のキーファイルを選択」で「新規作成」を選択。
ダイアログボックスで「キーファイル名」に任意のファイル名を指定。
「キーファイルをパスワードで保護する」は必須ではない。

次に、「ComVisible」属性を設定します。

ContextMenuExtension.cs
[ComVisible(true)]
public class ContextMenuExtension : SharpContextMenu
{
ContextMenuExtension.vb
<ComVisible(True)>
Public Class ContextMenuExtension
    Inherits SharpContextMenu

最後に、「COMServerAssociation」属性を設定します。SharpShell クラスで提供される属性です。どのファイルタイプと紐付するかを指定します。
ここでは拡張子が「.txt」のファイルと紐付するようにします。拡張子が「.txt」のファイルで右クリックしたときコンテキストメニューを拡張します。

ContextMenuExtension.cs
[ComVisible(true)]
[COMServerAssociation(AssociationType.ClassOfExtension, ".txt")]
public class ContextMenuExtension : SharpContextMenu
{
ContextMenuExtension.vb
<ComVisible(True)>
<COMServerAssociation(AssociationType.ClassOfExtension, ".txt")>
Public Class ContextMenuExtension
    Inherits SharpContextMenu

COMServerAssociation の詳細は以下のページを参照。
SharpShell - Documentation

ビルドする

ビルドするとアセンブリファイルが作成されます。これを COM サーバとして Windows に登録します。

COM サーバとして登録する

C# または VB.NET で作成したアセンブリファイルを COM サーバとして登録するには、.NET Framework に同梱されている「regasm」ツールを使います。

regasm ContextMenuExtension.dll /codebase

ただしこれは、.NET Framework がインストールされた時点でパスが通っていないので、使いづらいですね。
そこで、SharpShell ライブラリの作者が配布している「srm」ツールを使います。

SharpShell - Download

srm install ContextMenuExtension.dll -codebase

おわりに

以下の記事も書いています。

.NET で Windows エクスプローラのドラッグ&ドロップを拡張 - Qiita

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
38