アンセケターメンはてなエディション

いつどこで誰に見られても恥ずかしいコードが置かれています

ChromeやEdgeでエクスプローラを起動してフォルダを開く

2022年6月にInternet ExplorerIE)が終了しました。

社内のSMB共有ファイルサーバにファイルやフォルダがあって、IEでリンク集みたいなHTMLファイルからアクセスする運用をしていないでしょうか。
後継であるEdgeやChromeでは、IEと違ってリンクからファイルを直接開いたり、エクスプローラを起動させたりできなくなりました。なんということ!!
一応file:プロトコルでアクセスはできますが、フォルダはよくわからんリストになるし、ファイルを開こうとすると一旦ダウンロードという形になるんですよね。 xlsxをExcelで直接開けない!IEだと開けたのに!みたいな。

そんなときのために、IEと(ほぼ)同じ感じでファイルやフォルダにアクセスするための手段を作りました。
セキュリティ厳しめのところでもできるように、Windowsにもともと入っている機能だけで作っていきます。

成果物はGitHubに上げてあります。仕組みを知りたいよって人は続きへどうぞ。

github.com

1. カスタムURIスキーム

今回は「カスタムURIスキーム」というものを使います。

たとえばmailto:を最初につけてメールアドレスを入力するとメーラーが起動しますが、これってmailto:で始まるアドレスにアクセスするとメーラーWindowsが起動してくれるんですよね。
そして、mailtoの代わりに任意の文字列で始まるURIスキーム、すなわちカスタムURIスキームを登録することもできます。

今回はxopernerという文字列で実施します。xopener:で始まるアドレスにブラウザからアクセスすると、今回作るソフトが起動して、エクスプローラーを開いてくれるっていう流れです。

どうやって登録するかというと、レジストリをいじくります。以下にxopener.regの一部を抜粋します。

[HKEY_CURRENT_USER\Software\Classes\xopener]
@="URL:xopener Protocol"
"URL Protocol"=""

[HKEY_CURRENT_USER\Software\Classes\xopener\shell\open\command]
@="C:\\xopener\\xopener.exe \"%1\""

xopenerってなってるところがいくつかありますが、そこをいじれば任意のURLスキームを登録できます。

最後の行は開くアプリケーションを設定します。今回はCドライブ直下のxopenerってフォルダの中にあるxopener.exeを実行します。

HKEY_CLASSES_ROOTに書き込むと管理者権限要るかなーと思ってHKEY_CURRENT_USERにしたけど結局regeditするところでUACが出てくるという。

2. エクスプローラーを開くためのアプリケーション

頑張ればPowerShellとかで作れなくもないとは思いますが、めんどうなのでC#で作ります。

以下にxopener.csのすべてを掲載します。全部で38行です。

using System;
using System.Diagnostics;
using System.IO;
using System.Media;
using System.Web;
using System.Windows.Forms;

public class Program
{
    public static void Main(string[] args)
    {
        if (args.Length > 0)
        {
            // 何か引数がある場合
            // カスタムURLスキームでは1番目の引数に「xopener:ファイルパス」が入る
            // URLエンコードされてるのでデコードして、冒頭のxopener:も消す
            var path = HttpUtility.UrlDecode(args[0]).Replace('/','\\').Replace("xopener:","");

            if (File.Exists(path) || Directory.Exists(path))
            {
                // ファイル・フォルダが存在するなら開く
                Process.Start("explorer.exe", path);
            }
            else
            {
                // ファイル・フォルダが存在しない
                SystemSounds.Beep.Play();
                MessageBox.Show(path + " は存在しません", "エラー", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }
        else
        {
            // 引数がおかしい
            SystemSounds.Beep.Play();
            MessageBox.Show("起動には引数が必要です", "エラー", MessageBoxButtons.OK, MessageBoxIcon.Error);
        }
    }
}

たとえばCドライブ直下を開くためのリンクxopener:C:\を入力すると、このプログラムにはxopener:C:\っていう文字列が第1引数として渡されます。

最初のxopener:を取って、ファイルかフォルダが存在するなら開く。存在しないならエラーを出す。それだけ。

3. コンパイル・インストール

さっきのC#ソースコードコンパイルレジストリ登録のバッチファイルを作ります。

なぜコンパイルするかというと、exe配布だと署名が云々などというセキュリティ的な事情により実行できないからです。
自分でコンパイルすればセキュリティ通過できるので。

以下はinstall-xopener.batの中身です。

@echo off

"C:\Windows\Microsoft.NET\Framework64\v4.0.30319\csc.exe" /t:winexe ./xopener.cs

regedit /s %~dp0%xopener.reg

pause

コンパイルWindowsなら基本的に入ってる.NET Frameworkコンパイラで行います。Windows10では動いてますが、Windows11だとcsc.exeのパスが変わってるかも?

4. ホワイトリスト登録(失敗)

さて、ここまでの作業だけだとChromeで開くときに毎回確認メッセージが出ます。邪魔なのでホワイトリスト登録します。

[HKEY_CURRENT_USER\Software\Policies\Google\Chrome\URLAllowList]
"255"="xopener:*"

[HKEY_CURRENT_USER\Software\Policies\Microsoft\Edge\URLAllowList]
"255"="xopener:*"

こんな感じにしとけば確認メッセージが消え…消えねえ!!!

なんかバージョン100前後からセキュリティ上の問題で塞がれたみたいですね。gpeditでいじればいけるみたいな噂を聞いたけど面倒なのでこのままとします。

5. 動作確認

こういう感じのリンクを踏むとエクスプローラーでCドライブが開くはずです。

<a href="xopener:C:\">Cドライブ</a>

Cドライブ

おわり。

参考

ブラウザ上のリンクから任意のデスクトップアプリのファイルを開けると超便利 - Qiita

カスタム URL スキーム の 設定 と 利用 - galife

HKEY_CURRENT_USER\Software\Policies\Microsoft\Edge\URLWhitelist not respected - Microsoft Community Hub