はじめに
僕は以前 Delphi で Windows のシェル拡張(Shell Extension)を使っでエクスプローラに機能を追加するアプリを作りました。
[簡単エクスプローラ拡張 EzExpEx]
(http://hp.vector.co.jp/authors/VA029585/EzExpEx/)
これは残念なことに 64 ビット Windows のエクスプローラで動かないんですよね。僕が持っている Delphi では 64 ビット Windows アプリを作れないんです。
これを VB.NET で作り直したいとずっと思っていました。
そのために調べていると次の記事がありました。
[.NET Shell Extensions - Shell Context Menus - CodeProject] (http://www.codeproject.com/Articles/512956/NET-Shell-Extensions-Shell-Context-Menus)
これは C# で書かれています。
このまま使ってもいいのですが、僕は VB が好きなので移植することにしました。
Windows シェル拡張でコンテキストメニュー
エクスプローラで右クリックするとコンテキストメニューが表示されます。このメニューに独自の項目を追加します。
プロジェクトを作る
まず、「クラスライブラリ」のプロジェクトを新規作成します。
ここではプロジェクト名を「ContextMenuExtension」にします。* 元記事と違います。
次に、プロジェクトの「参照」設定に以下のアセンブリを追加します。
- System.Windows.Forms
- System.Drawing
IDE が作成したソースファイル「Class1.cs」または「Class1.vb」を「ContextMenuExtension.cs」または「ContextMenuExtension.vb」にリネームします。* 好きなファイル名で構いません。
SharpShell ライブラリを使う
「SharpShell」ライブラリを使います。
以下のページで配布されています。
[SharpShell - CodePlex]
(http://sharpshell.codeplex.com/)
「SharpShel.dll」を使います。これをプロジェクトの「参照」に追加します。
これを手作業してもいいけれど、Nuget を使うのが楽です。
SharpContextMenu から派生する
「ContextMenuExtension」クラスを「SharpContextMenu」から派生するよう書換します。
public class ContextMenuExtension : SharpContextMenu
{
Public Class ContextMenuExtension
Inherits SharpContextMenu
IDE が「抽象クラスの実装」を助言してくるので従って以下のメソッドを実装します。
- CanShowMenu
- CreateMenu
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;
}
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」。選択したファイルの名称と行数を表示します。
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());
}
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」属性を設定します。
[ComVisible(true)]
public class ContextMenuExtension : SharpContextMenu
{
<ComVisible(True)>
Public Class ContextMenuExtension
Inherits SharpContextMenu
最後に、「COMServerAssociation」属性を設定します。SharpShell クラスで提供される属性です。どのファイルタイプと紐付するかを指定します。
ここでは拡張子が「.txt」のファイルと紐付するようにします。拡張子が「.txt」のファイルで右クリックしたときコンテキストメニューを拡張します。
[ComVisible(true)]
[COMServerAssociation(AssociationType.ClassOfExtension, ".txt")]
public class ContextMenuExtension : SharpContextMenu
{
<ComVisible(True)>
<COMServerAssociation(AssociationType.ClassOfExtension, ".txt")>
Public Class ContextMenuExtension
Inherits SharpContextMenu
COMServerAssociation の詳細は以下のページを参照。
[SharpShell - Documentation]
(http://sharpshell.codeplex.com/documentation/)
ビルドする
ビルドするとアセンブリファイルが作成されます。これを COM サーバとして Windows に登録します。
COM サーバとして登録する
C# または VB.NET で作成したアセンブリファイルを COM サーバとして登録するには、.NET Framework に同梱されている「regasm」ツールを使います。
regasm ContextMenuExtension.dll /codebase
ただしこれは、.NET Framework がインストールされた時点でパスが通っていないので、使いづらいですね。
そこで、SharpShell ライブラリの作者が配布している「srm」ツールを使います。
[SharpShell - Download]
(http://sharpshell.codeplex.com/releases/)
srm install ContextMenuExtension.dll -codebase
おわりに
以下の記事も書いています。
[.NET で Windows エクスプローラのドラッグ&ドロップを拡張 - Qiita]
(http://qiita.com/tinymouse/items/2b916fa904047bf1b404)