はじめに
プリザンターからwindowsのエクスプローラを開きたい、という 強い願望 があったりしないでしょうか。
例えば
- ファイル数が多く、プリザンター内で探すより 社内ストレージ上の特定フォルダを開きたい
- プリザンター外で生成・加工されたファイルを確認するとき、該当フォルダにすぐ飛びたい
こういった要望は、社内ローカルにインストールして使うプリザンターの 宿命的機能 だと感じています。
とはいえ、昨今のブラウザはセキュリティがとにかく厳しいです。
ひと昔前に流行った file:// を使う方法は、現実的ではないことが多く、新規開発として積極的におすすめもしづらいです。
<a href="file:///C:/ほげほげ">フォルダを開く</a>
様々なファイルオープンの方法はあるかと思いますが、今回は、Web から カスタム URL スキーム経由でネイティブアプリを起動する 方法 (カスタム URL スキーム連携) で実装していきます。
全体の流れ
WindowsでカスタムURLスキーム連携を行うために次の3ステップで進めます。
- C# のコンソールアプリ
OpenFolder.exeを作成 - Windows のレジストリに
-
openfolder://...という独自プロトコルを登録 - そのプロトコルを受けるアプリとして
OpenFolder.exeを関連付け
-
- Web画面では
-
<a href="openfolder://C:/ほげほげ">のようなリンク - または JS で
location.href = "openfolder://...";
-
動きとしては、
クリック → ブラウザが「外部アプリ開きますか?」 → OpenFolder.exe → エクスプローラー起動、という流れです。
1.フォルダオープン用のコンソールアプリを作成
独自プロトコル openfolder://... で渡された情報を受け取り、指定したフォルダを Windows のエクスプローラーで開く ための小さなコンソールアプリを作成します。
プリザンター(Web 側)から openfolder://C:/ほげほげ のようなリンクを踏むと、ブラウザは OS に対して「このプロトコルを処理できるアプリを起動してよいか」を確認し、許可されると登録済みのアプリが起動します。今回作る OpenFolder.exe は、その起動先として動作します。
開発環境
- Visual Studio 2022
- C# 8.0
- プロジェクト名: OpenFolder
- 種別: コンソールアプリ(.NET)
文字コードやターゲットフレームワークは、社内標準に合わせれば特に問題ありません。
実装コード
using System.Diagnostics;
namespace OpenFolder
{
internal static class Program
{
[STAThread]
static void Main(string[] args)
{
// プロトコル呼び出し時は引数1つが渡される想定
if (args.Length == 0)
{
return;
}
try
{
// 例: "openfolder://C:/path/to/folder" のような形式
string raw = args[0];
// 自作プロトコル部分を削除
string path = raw.Replace("openfolder://", "");
// URLエンコードされた文字列をデコード
path = Uri.UnescapeDataString(path);
// Web側の "/" を Windows向け "\" に変換
path = path.Replace("/", "\\");
// ドライブレター補正
// Webでは "C/path" の形になり ":" が抜ける可能性があるため補完する
if (path.Length >= 2 && char.IsLetter(path[0]) && path[1] != ':')
{
path = path[0] + ":" + path.Substring(1);
}
// Explorerにパスを渡して開く
Process.Start("explorer.exe", path);
}
catch
{
// 必要に応じてログや例外処理を追加可能
}
}
}
}
ポイント
作成時にハマったポイントを記載。
- URL エンコードされていて日本語パスがそのままだと死ぬので UnescapeDataString 必須
- パスが存在しない場合の挙動(何も起きないので“壊れた感”が出る)
- ブラウザや呼び出し方で : が欠けるケースがある
- NlogやWinFormsでメッセージボックスを出力するなど、ログを出力する設計を行った方が後々の助けになりますが、ここでは省略します
2.Windowsのレジストリにフォルダオープン用のコンソールアプリを登録
前章で作成した OpenFolder.exe を、openfolder://... という 独自プロトコル(カスタム URL スキーム)で起動できるようにします。
Windows では「openfolder:// で始まる URL がクリックされたら、このアプリを呼び出す」という関連付けを レジストリ に登録することで実現できます。
本番運用ではインストーラ(WiX / Inno Setup など)や GPO で配布するのが一般的ですが、ここでは仕組みが分かりやすいように .reg の例で説明します。
登録するレジストリの例(.reg)
以下は openfolder:// を受けたら OpenFolder.exe を起動する設定例です。
OpenFolder.exe の配置先は環境に合わせて変更してください。
Windows Registry Editor Version 5.00
[HKEY_CLASSES_ROOT\openfolder]
@="URL:Open Folder Protocol"
"URL Protocol"=""
[HKEY_CLASSES_ROOT\openfolder\shell]
[HKEY_CLASSES_ROOT\openfolder\shell\open]
[HKEY_CLASSES_ROOT\openfolder\shell\open\command]
@="\"C:\\Program Files\\OpenFolder\\OpenFolder.exe\" \"%1\""
ポイント
-
openfolderがプロトコル名
openfolder://で始まるURLがこの設定に飛んできます - パスは実際に配布する exe のパスに変更してください
例:C:\Program Files\OpenFolder\OpenFolder.exe -
%1にopenfolder://....そのものが渡されるので、上の C# コードで解釈しているイメージです
社内配布するなら、GPOやインストーラでこのレジストリ登録を行うのが現実的です。
3.Web側の実装例
単純なリンク
最もシンプルなのは <a> タグでリンクを作る方法です。
<a href="openfolder://C:/ほげほげ">ほげほげフォルダを開く</a>
ボタン & JavaScript
UI をボタンにしたい場合は、クリック時に location.href を書き換えるのが手軽です。
パスに日本語や空白が含まれる可能性があるので、encodeURI(または状況により encodeURIComponent)で URL エンコードしておくと安心です。
<button id="btnOpen">フォルダを開く</button>
<script>
document.getElementById('btnOpen').addEventListener('click', () => {
const path = 'C:/ほげほげ';
// シンプルに location.href で OK
location.href = 'openfolder://' + encodeURI(path);
});
</script>
ブラウザ側の挙動について
ブラウザによって表現は多少違いますが、基本的にはクリック時に
- 「外部アプリを開きますか?」の確認ダイアログが表示される
- ユーザーが許可すると OpenFolder.exe が起動する
- 指定フォルダでエクスプローラーが開く
という流れになります。
4.プリザンターに組み込む
プリザンターにログインし、まずは動作確認用に 記録テーブル を作成します。
管理ボタン からテーブルの管理 を選択します。
エディタ を選択し、任意の項目を選択し 詳細設定 を選択します。
今回は 分類A 分類B にそれぞれ追加してみました。
※ ここでは 分類A にフォルダオープンボタンを追加します。
分類A を選択し 詳細設定 を選択します。
拡張HTML を選択し「フィールドの後」に以下の項目を追加します。
フィールドの後に追加する項目
<button id="btnOpen" class="glow-button">フォルダを開く</button>
<script>
document.getElementById('btnOpen').addEventListener('click', () => {
const path = 'E:/提出物';
// シンプルに location.href で OK
location.href = 'openfolder://' + encodeURI(path);
});
</script>
コントロールの後
また、標準ボタンがイマイチと思われる方がいらっしゃると思いますので、見た目だけステキな感じにしておきます。
※ すでにプリザンター側の CSS などがある場合は、クラス名が衝突しないように調整してください。
<style>
.glow-button {
padding: 10px 18px;
font-size: 14px;
border: none;
border-radius: 6px;
background: #3b82f6;
color: white;
cursor: pointer;
transition: box-shadow 0.25s, transform 0.15s;
box-shadow: 0 0 0px rgba(80,150,255,0.0);
}
.glow-button:hover {
box-shadow: 0 0 12px rgba(80,150,255,0.85);
transform: translateY(-2px);
}
.glow-button:active {
transform: translateY(0);
box-shadow: 0 0 6px rgba(80,150,255,0.65);
}
</style>
実際の画面
5.実行してみる
プリザンターに1件データを登録し、エディタ状態に遷移するとボタンが表示されます。
ボタンをクリックすると、拡張HTMLで指定したディレクトリが開きます。
※ チェックボタンをONにして選択すると、以後ポップアップが出る事はありません。
6.さいごに
今回は、プリザンターの画面から Windows のエクスプローラーを開くために、カスタム URL スキーム + 小さなコンソールアプリ という構成で実装してみました。
一方で、この方式は便利な反面、セキュリティや運用面の前提がけっこう大事です。
- ユーザー端末に
OpenFolder.exeとレジストリ登録が必要
(社内の配布方法は環境次第なので、まずは小さく検証してから運用に乗せるのが安心です) - どのパスでも開けてしまうと危険なので、必要なら 許可フォルダのホワイトリスト をアプリ側に入れるのがおすすめ
- パスに日本語や空白が含まれることがあるため、Web 側では URL エンコード、アプリ側では URL デコード を前提にしています
(例:Web 側encodeURI、アプリ側Uri.UnescapeDataString) - 実運用では、存在しないパスを指定した場合に備えて
Directory.Existsなどでチェックし、必要なら メッセージ表示やログ出力 を入れると安心です - 配布する
OpenFolder.exeは、できれば 改ざんされにくい場所で管理 し、想定外の置き換えが起きないようにしておくと安全です
小さな仕組みですが、プリザンターを起点に「必要な場所へ最短で飛べる導線」を作れるので、刺さる業務があればぜひ試してみてください。





