エクスプローラーのコンテキストメニュー(右クリックメニュー)に独自メニューを追加する方法

## 概要
これは、エクスプローラー上で右クリックしたときに表示されるコンテキストメニューに、独自の項目を追加する方法を調査したときのメモである。

まとめは最下部に。

## きっかけ
[Scoop](https://scoop.sh/)で[Visual Studio Code](https://azure.microsoft.com/ja-jp/products/visual-studio-code/)をインストールしたときに次のように促された。

```
Add Visual Studio Code as a context menu option by running: \"$dir\\vscode-install-context.reg\"
```

(`vscode-install-context.reg`を実行してVisual Studio Codeをコンテキストメニューに追加)

右クリックでアプリを開く仕組みは前々からなんとなく知っていたが、なんとなくしか知らなかったのでこの機会にこれを教材として調べてメモしておく。

**お約束だけれど、レジストリを扱うときは自己責任で！**

## 調査時環境

* Windows10 バージョン1809
* Scoop a9fa775d
* Visual Studio Code scoopのextrasバケットの1.41.1


## 調査対象コード

以下が今回調査したファイルの一覧。

```
C:\Users\tatesuke\scoop\apps\vscode\1.41.1
├ Code.exe  ・・・ VSCode本体(※）
│・・・
├ vscode-install-context.reg    ・・・(1)
└ vscode-uninstall-context.reg  ・・・(2)
```
※VSCode本体は読まないけど構造をわかりやすくするために明示

それぞれについて解読していく。

## (1) `vscode-install-context.reg`

`vscode-install-context.reg`はその名の通り、vscodeの右クリックコンテキストメニューをインストールするレジストリ登録ファイル。ダブルクリックすると、コンテキストメニューに`Open with Code`が表示されるようになる。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/29682/45af554c-054c-7991-85d9-5da9ae41150d.png)

また、ファイル名から分かる通り、右クリックのコンテキストメニューに項目を追加するにはレジストリを利用する。レジストリそのものについてはそれだけで分厚い本1冊くらいかけるのだろうから、ここでは構造などあまり深追いせず書かれていることを読み解くことに専念する。

さて、このファイルは大した量でないので全文掲載させてもらう。

```vscode-install-context.reg
Windows Registry Editor Version 5.00

[HKEY_CURRENT_USER\Software\Classes\*\shell\Open with &Code]
@="Open with &Code"
"Icon"="C:\\Users\\tatesuke\\scoop\\apps\\vscode\\current\\Code.exe"
[HKEY_CURRENT_USER\Software\Classes\*\shell\Open with &Code\command]
@="\"C:\\Users\\tatesuke\\scoop\\apps\\vscode\\current\\Code.exe\" \"%1\""

[HKEY_CURRENT_USER\Software\Classes\Directory\shell\Open with &Code]
@="Open with &Code"
"Icon"="C:\\Users\\tatesuke\\scoop\\apps\\vscode\\current\\Code.exe"
[HKEY_CURRENT_USER\Software\Classes\Directory\shell\Open with &Code\command]
@="\"C:\\Users\\tatesuke\\scoop\\apps\\vscode\\current\\Code.exe\" \"%1\""

[HKEY_CURRENT_USER\Software\Classes\Directory\Background\shell\Open with &Code]
@="Open with &Code"
"Icon"="C:\\Users\\tatesuke\\scoop\\apps\\vscode\\current\\Code.exe"
[HKEY_CURRENT_USER\Software\Classes\Directory\Background\shell\Open with &Code\command]
@="\"C:\\Users\\tatesuke\\scoop\\apps\\vscode\\current\\Code.exe\" \"%V\""
```

色々書いてあるがじっくり読むと以下の2つの塊が連なっているようだ。

* `[HKEY_CURRENT_USER\Software\Classes\拡張子\キー名]`
* `[HKEY_CURRENT_USER\Software\Classes\拡張子\キー名\command]`


### 拡張子

`HKEY_CURRENT_USER\Software\Classes`配下に拡張子の名前でキーを作ることで、その拡張子のファイルに関する定義を記述できる。例えば、`HKEY_CURRENT_USER\Software\Classes\.txt`を定義すれば`.txt`ファイルについての定義を記載できる。

ただ、vscodeでは具体的な拡張子ではなく以外の3つが定義されている。

| キー名 | 表示タイミング |
|:-----------|:------------|
| Directory       | ディレクトリを右クリックしたとき |
| Directory\Background     | ファイルでもディレクトリでもない、背景部分を右クリックしたとき |
| *       | 上記以外を右クリックしたとき |


### 見た目の定義

`[HKEY_CURRENT_USER\Software\Classes\拡張子\キー名]`でコンテキストメニューに表示される文字列とアイコンが指定されている。
`*`に関する部分を以下に抜粋する。

```
[HKEY_CURRENT_USER\Software\Classes\*\shell\Open with &Code]
@="Open with &Code"
"Icon"="C:\\Users\\tatesuke\\scoop\\apps\\vscode\\current\\Code.exe"
```

1行目の`Open with &Code`がキー名となっている。空白が入って個人的に気持ち悪いが、構わないらしい。ここでは表示される文字列と同じになっているが、別にそうでなくても構わない。

2行目の`@=`でコンテキストメニューに表示する文字列を指定している。試したら日本語も使えるようだ[^1]。`&`は表示されないが、直後のアルファベットがショートカットキーになるようで、キーボードの同じキーを押すとこの項目がフォーカスされる[^2]。

[^1]: ただし、`.reg`ファイルとする場合、ファイルの文字コードは`BOMつきUTF-8`か、`Shift_JIS`を利用しなければならない
[^2]: この`&`の名前を知りたいのでご存知でしたら誰か教えてください。

3行目は、コンテキストメニューに表示されるアイコンを指定している。ここではexeファイルを指定しているが、このファイルを実行するのではなく、埋め込まれたアイコンを表示するということらしい。





### 動作の定義

`[HKEY_CURRENT_USER\Software\Classes\拡張子\キー名\command]`でメニューをクリックしたときに実行されるコマンドを定義している。`*`についての定義部分を抜粋する。


```
[HKEY_CURRENT_USER\Software\Classes\*\shell\Open with &Code\command]
@="\"C:\\Users\\tatesuke\\scoop\\apps\\vscode\\current\\Code.exe\" \"%1\""
```

詳細な説明はいらないように思えるが実行ファイルとパラメータを指定している。`%1`は右クリックしたファイルのフルパスに置き換えられるプレースホルダーで、他にもいくつかのプレースホルダーが利用できる。その他のプレースホルダーについては、以下ページの`コマンドラインに指定できるプレースホルダー`の項目が詳しい。

> Windows レジストリ 解剖記
> https://www.pg-fl.jp/program/winreg/classes.htm#ext_cmdline_placeholder

`Directory\Background`（背景部分右クリック時のコンテキストメニュー）では選択しているファイルがないので、以下のように`%1`でなく`%V`を使って現在のディレクトリのパスを渡している。

```
[HKEY_CURRENT_USER\Software\Classes\Directory\Background\shell\Open with &Code\command]
@="\"C:\\Users\\tatesuke\\scoop\\apps\\vscode\\current\\Code.exe\" \"%V\""
```


なお、試した限り`%PATH%`などの環境変数は使えなかった。使い方やお作法があるのかもしれない（レジストリと環境変数についてもっと深く理解できていればこんな疑問は抱かないのかもしれない）。




## (2) `vscode-uninstall-context.reg`

`vscode-uninstall-context.reg`は、右クリックコンテキストメニューをアンインストールするレジストリ登録ファイル。

やっていることはレジストリのキーを削除しているだけ。

```
[-HKEY_CURRENT_USER\Software\Classes\*\shell\Open with &Code]
[-HKEY_CURRENT_USER\Software\Classes\*\shell\Open with &Code\command]
[-HKEY_CURRENT_USER\Software\Classes\Directory\shell\Open with &Code]
[-HKEY_CURRENT_USER\Software\Classes\Directory\shell\Open with &Code\command]
[-HKEY_CURRENT_USER\Software\Classes\Directory\Background\shell\Open with &Code]
[-HKEY_CURRENT_USER\Software\Classes\Directory\Background\shell\Open with &Code\command]
```

ハイフン('-')をつけて'[-キー名]'として書くと削除されるようだ。

## まとめ

右クリックコンテキストメニューに項目を追加するには以下のレジストリキーを定義する

* `[HKEY_CURRENT_USER\Software\Classes\拡張子\キー名]`
    * 文字列とアイコンを指定する
    * 拡張子のほか、`Directory`、`Directory\Background`、`*`が使える
* `[HKEY_CURRENT_USER\Software\Classes\拡張子\キー名\command]`
    * 実行ファイルを指定する

コンテキストメニューの項目を削除するには上記のレジストリキーを削除する。



以上