はじめに
以前に僕は Delphi で Windows のシェル拡張(Shell Extension)を使っでエクスプローラに機能を追加するアプリを作りました。
[簡単エクスプローラ拡張 EzExpEx]
(http://hp.vector.co.jp/authors/VA029585/EzExpEx/)
これは残念なことに 64 ビット Windows のエクスプローラで動かないんですよね。僕が持っている Delphi では 64 ビット Windows アプリを作れないんです。
これを VB.NET で作り直したいとずっと思っていました。
そのために調べていると次の記事がありました。
[.NET Shell Extensions - Shell Drop Handlers - CodeProject]
(http://www.codeproject.com/Articles/529515/NET-Shell-Extensions-Shell-Drop-Handlers)
これは C# で書かれています。
このまま使ってもいいのですが、僕は VB が好きなので移植することにしました。
Windows シェル拡張でドロップハンドラ
エクスプローラでドラッグしてドロップしたとき、独自の処理するよう機能を追加します。
プロジェクトを作る
まず、「クラスライブラリ」のプロジェクトを新規作成します。
ここではプロジェクト名を「DragDropExtension」にします。* 元記事と違います。
次に、プロジェクトの「参照」設定に以下のアセンブリを追加します。
- System.Windows.Forms
- System.Drawing
IDE が作成したソースファイル「Class1.cs」または「Class1.vb」を「DragDropExtension.cs」または「DragDropExtension.vb」にリネームします。* 好きなファイル名で構いません。
SharpShell ライブラリを使う
「SharpShell」ライブラリを使います。
以下のページで配布されています。
[SharpShell - CodePlex]
(http://sharpshell.codeplex.com/)
「SharpShel.dll」を使います。これをプロジェクトの「参照」に追加します。
これを手作業してもいいけれど、Nuget を使うのが楽です。
SharpDropHandler から派生する
「DragDropExtension」クラスを「SharpDropHandler」から派生するよう書換します。
public class DragDropExtension : SharpDropHandler
{
Public Class DragDropExtension
Inherits DropHandler
IDE が「抽象クラスの実装」を助言してくるので従って以下のメソッドを実装します。
- DragEnter
- Drop
protected override void DragEnter(DragEventArgs dragEventArgs)
{
// ドラッグしたファイルの拡張子が ".txt" ならコピー可能、そうでなければコピー不可のアイコンにする
dragEventArgs.Effect =
DragItems.All(di => string.Compare(Path.GetExtension(di), ".txt", StringComparison.InvariantCultureIgnoreCase) == 0)
? DragDropEffects.Copy : DragDropEffects.None;
}
protected override void Drop(DragEventArgs dragEventArgs)
{
// ドロップしたときの処理
CountLines();
}
Protected Overrides Sub DragEnter(dragEventArgs As DragEventArgs)
'ドラッグしたファイルの拡張子が ".txt" ならコピー可能、そうでなければコピー不可のアイコンにする
dragEventArgs.Effect = DragItems.All(Function(ByVal di) _
If(String.Compare(IO.Path.GetExtension(di), ".xml", StringComparison.InvariantCultureIgnoreCase) = 0, _
DragDropEffects.Link, DragDropEffects.None))
End Sub
Protected Overrides Sub Drop(dragEventArgs As DragEventArgs)
'ドロップしたときの処理
CountLines()
End Sub
主な機能は「CountLines」。選択したファイルの名称と行数を表示します。* 元記事と違います。
private void CountLines()
{
var builder = new StringBuilder();
foreach (var path in DragItems)
{
builder.AppendLine(string.Format("{0} - {1} 行", IO.Path.GetFileName(path), IO.File.ReadAllLines(path).Length));
}
builder.AppendLine(String.Format("To: {0}", SelectedItemPath))
// メッセージボックスで表示する
MessageBox.Show(builder.ToString());
}
Private Sub CountLines()
Dim builder As New StringBuilder
For Each path In DragItems
builder.AppendLine(String.Format("{0} - {1} 行", IO.Path.GetFileName(path), IO.File.ReadAllLines(path).Length))
Next
builder.AppendLine(String.Format("To: {0}", SelectedItemPath))
'メッセージボックスで表示する
MessageBox.Show(builder.ToString)
End Sub
SharpDropHandler クラスの DragItems で、エクスプローラで選択したファイルを取得できます。
また、SelectedItemPath で、ドロップ先のファイルまたはフォルダのパスを取得できます。
COM サーバ登録機能を実装する
作成しているクラスライブラリが COM サーバとして登録できるようにします。
まず、アセンブリを COM 参照可能にします。以下の手順で作業します。* 元記事にないようです。
プロジェクトの「プロパティ」を開く。
「アプリケーション」タブを選択。
「アセンブリ情報」を押下。
ダイアログボックスで「アセンブリを COM 参照可能にする」にチェック。
次に、アセンブリに署名します。以下の手順で作業します。
プロジェクトの「プロパティ」を開く。
「署名」タブを選択。
「アセンブリに署名する」をチェック。
「厳密な名前のキーファイルを選択」で「新規作成」を選択。
ダイアログボックスで「キーファイル名」に任意のファイル名を指定。
「キーファイルをパスワードで保護する」は必須ではない。
次に、「ComVisible」属性を設定します。
[ComVisible(true)]
public class DragDropExtension : SharpDropHandler
{
<ComVisible(True)>
Public Class DragDropExtension
Inherits SharpDropHandler
最後に、「COMServerAssociation」属性を設定します。SharpShell クラスで提供される属性です。どのファイルタイプと紐付するかを指定します。
ここでは拡張子が「.txt」のファイルと紐付するようにします。拡張子が「.txt」のファイルにドロップしたとき機能が実行されます。
[ComVisible(true)]
[COMServerAssociation(AssociationType.ClassOfExtension, ".txt")]
public class DragDropExtension : SharpDropHandler
{
<ComVisible(True)>
<COMServerAssociation(AssociationType.ClassOfExtension, ".txt")>
Public Class DragDropExtension
Inherits SharpDropHandler
COMServerAssociation の詳細は以下のページを参照。
[SharpShell - Documentation]
(http://sharpshell.codeplex.com/documentation/)
ビルドする
ビルドするとアセンブリファイルが作成されます。これを COM サーバとして Windows に登録します。
COM サーバとして登録する
C# または VB.NET で作成したアセンブリファイルを COM サーバとして登録するには、.NET Framework に同梱されている「regasm」ツールを使います。
regasm DragDropExtension.dll /codebase
ただしこれは、.NET Framework がインストールされた時点でパスが通っていないので、使いづらいですね。
そこで、SharpShell ライブラリの作者が配布している「srm」ツールを使います。
[SharpShell - Download]
(http://sharpshell.codeplex.com/releases/)
srm install DragDropExtension.dll -codebase
おわりに
以下の記事も書いています。
[.NET で Windows エクスプローラのコンテキストメニューを拡張 - Qiita] (http://qiita.com/tinymouse/items/eb8aebb39ddd5c103347)