【Delphi】環境変数 (が指す先) を Explorer で開く【超初心者向け】

# はじめに

巷では **ノーコード** とか **ローコード** とやらが流行っているようですね。流石にノーコードとまではいきませんが、ローコードの範疇でアプリケーションを作ってみようと思います。

では、早速やっていきましょう。アプリケーションを作るのに必要な Delphi は **『 12.1 Community Edition』** (無償版) で大丈夫です。

 - [Delphi Community Edition (Embarcadero)](https://www.embarcadero.com/jp/products/delphi/starter)
 - [EDN アカウントを作りたい (Support Wiki)](https://docwiki.embarcadero.com/Support/ja/EDN%E3%82%A2%E3%82%AB%E3%82%A6%E3%83%B3%E3%83%88%E3%82%92%E4%BD%9C%E3%82%8A%E3%81%9F%E3%81%84)

# 環境変数 (が指す先を) を Explorer で開くアプリを作る

環境変数には特定のフォルダを指しているものがあります。これを Explorer で開くアプリを作ります。

## どんなの？

Delphi IDE で `[ツール | オプション]` でオプションダイアログを開くと、その中に**環境変数**という項目があります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/21785/5ae922c8-6aa6-42ed-a426-0babfb363cf3.png)

このうち `BDS～` で始まる環境変数は、そこに設定されているフォルダをたまに参照したい時があるのです。

| 環境変数 | パス |
|:---|:---|
| BDS | RAD Studio のインストール先 |
| BDSBIN | 実行ファイルの格納先 |
| BDSCatalogRepository | GetIt でインストールしたもの |
| BDSCatalogRepositoryAllUsers | GetIt インストーラでインストールされたもの。Android SDK などもここにある |
| BDSCOMMONDIR | RAD Studio の共通フォルダ。BPL や DCP、CatalogRepository、サンプルデモなどの親フォルダ |
| BDSINCLUDE | インクルードファイルの格納先 |
| BDSLIB | ライブラリファイルの格納先 |
| BDSPLATFORMSDKSDIR | プラットフォーム SDK の格納先 |
| BDSPROJECTSDIR | プロジェクトファイル格納先 |
| BDSUSERDIR | CatalogRepository、インポートフォルダなどの親フォルダ  |

他にも次のようなものがあります。

| 環境変数 | パス |
|:---|:---|
| DELPHI | Delphi のインストール先 |
| DEMOSDIR | サンプルデモのインストール先 |


これらの環境変数が指す先を Explorer でサッと開こうと思ったら **RAD Studio コマンドプロンプト** を使うのが簡単です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/21785/4232b18d-0b09-4568-b6d4-aae1b6ce5d60.png)

次のようにしてインストール先のフォルダを開く事ができます。例では環境変数 **BDS** が指す先を Explorer で開いています。

```
explorer %BDS%
```

が、環境変数名が頭に浮かばなかったりして、"**サッと**" は開けない事も多いです。もちろん `SET` とタイプして環境変数を表示すればいいのですが...

```
C:\Embarcadero\Studio\23.0\bin64>set                                                           
...
BDS=C:\Embarcadero\Studio\23.0
BDSCOMMONDIR=C:\Users\Public\Documents\Embarcadero\Studio\23.0
BDSINCLUDE=C:\Embarcadero\Studio\23.0\include
...
```

すべての環境変数を参照できるわけではありません。

## そんなの [ツールの構成] でやれば？

**「そんなの [ツール | ツールの構成...] で Explorer を登録すればいいじゃないか！」** って思いますよね？

でも、実際にやってみたら開けないと思います [^1]。環境変数をパラメータとして設定する事はできず、できたように見えても思ったフォルダは開きません。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/21785/4e37cf18-aff7-4394-a0ab-10798e44b630.png)

:::note
[ツールの構成] で Explorer を登録できたとしても、10 個以上登録するのは面倒ですよね。
:::

一方、**RAD Studio コマンドプロンプト**を登録する事はできます。

| 名前 | 値 |
|:---|:---|
| タイトル | RAD Studio コマンド プロンプト |
| プログラム | C:\Windows\System32\cmd.exe |
| 作業フォルダ | C:\Embarcadero\Studio\23.0\bin |
| パラメータ | /K "C:\Embarcadero\Studio\23.0\bin\rsvars.bat" |

IDE から起動すれば環境変数がすべて見えます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/21785/d4c02f42-8aed-41eb-b861-75c0de774864.png)

```
C:\Embarcadero\Studio\23.0\bin64>set                                                           
...
BDS=C:\Embarcadero\Studio\23.0
BDSAppDataBaseDir=BDS                         
BDSBIN=c:\embarcadero\studio\23.0\bin
BDSCatalogRepository=C:\Users\deko\Documents\Embarcadero\Studio\23.0\CatalogRepository
BDSCatalogRepositoryAllUsers=C:\Users\Public\Documents\Embarcadero\Studio\23.0\CatalogRepository
BDSCOMMONDIR=C:\Users\Public\Documents\Embarcadero\Studio\23.0
BDSINCLUDE=C:\Embarcadero\Studio\23.0\include
BDSLIB=c:\embarcadero\studio\23.0\lib
BDSPLATFORMSDKSDIR=C:\Users\deko\Documents\Embarcadero\Studio\SDKs
BDSPROJECTSDIR=C:\Users\deko\Documents\Embarcadero\Studio\Projects
BDSUSERDIR=C:\Users\deko\Documents\Embarcadero\Studio\23.0
...
```

けれど、ここから `explorer～` って叩くのも面倒なんですよね。なので、IDE に表示されている 環境変数 (が指す先を) を Explorer で開くアプリが欲しくなってきます。

**See also:**

 - [［ツールの構成...］ (DocWiki)](https://docwiki.embarcadero.com/RADStudio/ja/［ツールの構成...］)

## そして
出来上がったものがこちらになります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/21785/558a94a2-a855-405e-8b30-9e8889bb81b9.png)

起動時にリストへ環境変数が指すパスを表示して、項目がダブルクリックされたら Explorer で開くというだけのアプリケーションです。

:::note
2025/05/09 ポップアップメニューで環境変数名やパスをクリップボードへコピーできるようにしました。
:::

### ソースコード

短いのでソースコードも掲載します。

```pascal:ObEV.dpr
program ObEV;

uses
  Vcl.Forms,
  frmuMain in 'frmuMain.pas' {frmMain};

{$R *.res}

begin
  Application.Initialize;
  Application.MainFormOnTaskbar := True;
  Application.Title := '環境変数で Explorer を開く';
  Application.CreateForm(TfrmMain, frmMain);
  Application.Run;
end.
```

```pascal:frmuMain.dfm
object frmMain: TfrmMain
  Left = 0
  Top = 0
  BorderIcons = [biSystemMenu]
  Caption = #29872#22659#22793#25968#12391' Explorer '#12434#38283#12367
  ClientHeight = 321
  ClientWidth = 784
  Color = clBtnFace
  Font.Charset = DEFAULT_CHARSET
  Font.Color = clWindowText
  Font.Height = -15
  Font.Name = 'Segoe UI'
  Font.Style = []
  Position = poScreenCenter
  OnCreate = FormCreate
  TextHeight = 20
  object lvList: TListView
    Left = 0
    Top = 0
    Width = 784
    Height = 321
    Align = alClient
    Columns = <
      item
        Caption = #29872#22659#22793#25968
        Width = 222
      end
      item
        Caption = #12497#12473
        Width = 540
      end>
    ReadOnly = True
    RowSelect = True
    PopupMenu = pmList
    TabOrder = 0
    ViewStyle = vsReport
    OnDblClick = lvListDblClick
  end
  object pmList: TPopupMenu
    Left = 336
    Top = 136
    object N1: TMenuItem
      Caption = #29872#22659#22793#25968#21517#12434#12434#12463#12522#12483#12503#12508#12540#12489#12395#12467#12500#12540
      OnClick = N1Click
    end
    object N2: TMenuItem
      Caption = #12497#12473#12434#12463#12522#12483#12503#12508#12540#12489#12395#12467#12500#12540
      OnClick = N2Click
    end
  end
end
```

```pascal:frmuMain.pas
unit frmuMain;

interface

uses
  Winapi.Windows, Winapi.Messages, Winapi.ShellAPI, System.SysUtils,
  System.Variants, System.Classes, Vcl.Graphics, Vcl.Controls, Vcl.Forms,
  Vcl.Dialogs, Vcl.ComCtrls, Vcl.Menus, Vcl.Clipbrd;

type
  TfrmMain = class(TForm)
    lvList: TListView;
    pmList: TPopupMenu;
    N1: TMenuItem;
    N2: TMenuItem;
    procedure FormCreate(Sender: TObject);
    procedure lvListDblClick(Sender: TObject);
    procedure N1Click(Sender: TObject);
    procedure N2Click(Sender: TObject);
  private
    { Private 宣言 }
  public
    { Public 宣言 }
  end;

var
  frmMain: TfrmMain;

implementation

{$R *.dfm}

procedure TfrmMain.FormCreate(Sender: TObject);
const
  EnvVars: array [0..11] of string =
    ('BDS', 'BDSBIN', 'BDSCatalogRepository', 'BDSCatalogRepositoryAllUsers',
     'BDSCOMMONDIR', 'BDSINCLUDE', 'BDSLIB', 'BDSPLATFORMSDKSDIR',
     'BDSPROJECTSDIR', 'BDSUSERDIR', 'DELPHI', 'DEMOSDIR');
begin
  for var i:=Low(EnvVars) to High(EnvVars) do
    with lvList.Items.Add do
    begin
      Caption := EnvVars[i];
      SubItems.Add(GetEnvironmentVariable(EnvVars[i]));
    end;
end;

procedure TfrmMain.lvListDblClick(Sender: TObject);
begin
  if lvList.ItemIndex < 0 then
    Exit;
  var Path := lvList.Items[lvList.ItemIndex].SubItems[0];
  if Path = '' then
    Exit;
  ShellExecute(0, 'open', 'explorer.exe', PChar(Path), nil, SW_SHOWNORMAL);
  Close;
end;

procedure TfrmMain.N1Click(Sender: TObject);
begin
  if lvList.ItemIndex < 0 then
    Exit;
  Clipboard.AsText := lvList.Items[lvList.ItemIndex].Caption;
end;

procedure TfrmMain.N2Click(Sender: TObject);
begin
  if lvList.ItemIndex < 0 then
    Exit;
  Clipboard.AsText := lvList.Items[lvList.ItemIndex].SubItems[0];
end;

end.
```

上記 3 ファイルを同じフォルダに保存し [^2]、`ObEV.dpr` を Delphi で開いてビルドすると `ObEV.exe` が得られます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/21785/af5e76c3-3ff8-4e4a-aa88-e204e50b4a9d.png)

これを `[ツール | ツールの構成...]` で登録して使います。

# おわりに

使い方は `ObEV.exe` を IDE に登録するだけなので、とても簡単です。(現行の Windows で動作させる限り) 複数バージョンの Delphi がインストールされていてもバージョン毎に `ObEV.exe` を作る必要はありません [^3]。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/21785/b1209df9-d811-4a61-b34d-538ee4ffc608.png)

古いバージョンだと存在しない環境変数があります。無効な環境変数が目障りだと感じる方は、リストから除外するようにコードを書き替えてみてください。

[^1]: マクロが使えるようになっているせいか、バグっぽい挙動があるんですよねぇ。
[^2]: すべて UTF-8 (with BOM) で構いません。
[^3]: [11 Alexandria](https://qiita.com/ht_deko/items/39dba17426cbbeb860d6) 以降で作られた実行ファイルは Windows XP では動作しません (デフォルト設定の場合)。