1. トップ
  2. 新着ニュース
  3. IT
  4. IT総合

Windowsでプログラムを実行するルールをあらためて掘り下げる

ASCII.jp / 2022年12月25日 10時0分

コマンドプロンプト(cmd.exe)で、何もないディレクトリから「xyzprog」を実行しようとするとエラーになる。しかし、startコマンドを使うと実行できる。このようにcmd.exeのコマンドラインとstartコマンドでは、異なるプログラム起動ルールが適用されている

 WindowsをはじめとしたUnixの影響を受けたOSには、プログラムの実行時にフルパスを指定することなく起動が可能な「検索パス(Search Path)」あるいは「コマンド検索パス」と呼ばれる機能がある。検索パスは、PATH環境変数に定義されたディレクトリのリストから実行ファイルを探す機能だ。Unix開発のきっかけともなったMulticsに装備され、Version 3 Unixに実装された。

 Windowsでは、システム環境変数/ユーザー環境変数の両方でPATH環境変数を定義できる。この環境変数のみ例外的に、システム環境変数、ユーザー環境変数の順に連結されてプロセス環境変数のPATH環境変数となる。

 Windowsの検索パスは、Unixのものをベースにしているが、MS-DOS、Windows用に改良され、プログラムの起動ルールの一部として使われている。大きな違いの1つは、MS-DOSでは、実行ファイルを拡張子で区別していた点だ。当時のハードウェアは性能が低く、記憶媒体もフロッピードライブで低速だったため、ファイルを読んで種類を判定していたのでは起動が遅くなってしまう。そこでファイルの中身ではなく、拡張子で種類を判断していた。

 Windowsでは、プログラムの実行はエクスプローラーやコンソール、ファイル名を指定して実行など、複数の場所から可能だ。このときのプログラム起動ルールを整理してみたい。まずは、わかりやすいコマンドラインでの実行方法を整理する。なお検証は、Windows 11 Ver.22H2(OSビルド22621.963)で行なっている。

実行ファイルの種類

 Windowsの実行ファイル形式はEXE形式のみだが、拡張子としては「.exe」と「.com」がある。「.com」は、MS-DOSのVer.1.0で定義された64KB以下のバイナリ実行ファイルの形式だった。

 そもそも、「.com」は、CP/M-80で8080バイナリ実行ファイルに使われていた拡張子で、MS-DOSのベースとなった86-DOSがCP/M-80の8086版クローンとして作られたため、この拡張子を使っている。ただし、今のWindowsでは16bitモードを廃止したため、拡張子は.comでも中身は.exeと同じである。これはWindowsに付属する「format.com」などの名前を変えないための対策だ。多くのスクリプトが、メディアの初期化コマンドとしてこの名前コマンドを起動しているからだ。

 また、MS-DOSでは、「.bat」の拡張子を持つBatchファイル(中身はテキストファイル)が実行ファイル扱いになっていた。「.com 「.exe」「.bat」は、MS-DOSのとき、拡張子を省略して指定することができた。環境変数による検索パスもサポートされ、このときも前記3つの拡張子を省略することができた。

 Windowsでは、こうしたMS-DOSでの慣習を引き継いだが、実行ファイル扱いとする拡張子をPATHEXT環境変数で指定できるようになった。標準では、Windows 95で追加されたWindows Scripting Host関連の拡張子やMicrosoftコンソール用の「.MSC」などが標準で登録されている。具体的には、

PATHEXT=.COM;.EXE;.BAT;.CMD;.VBS;.VBE;.JS;.JSE;.WSF;.WSH;.MSC

となっている。

 この環境変数に拡張子を登録することで、該当の拡張子を持ったファイルは、Batchファイル同様に実行ファイルとして扱われ、拡張子を省略して起動できる。これをこの記事では「PATHEXT実行」と呼ぶ。PATHEXT実行は、カレントディレクトリとPATH環境変数で指定されたディレクトリでのみ有効だ。

 さらにWindowsでは、「関連付け」を使って、拡張子と処理プログラムの対応を指定できるようになった。たとえば標準では、「.txt」ファイルはメモ帳に関連付けされている。このため、カレントディレクトリに「file.txt」があるとき、「file.txt」とコマンドラインに入力すると、メモ帳でfile.txtが開く。データファイルは実行ファイルではないが、見かけ上、「.txt」を持つファイルは、notepad.exeを起動する。この起動方法を本記事では「関連付け起動」と呼ぶことにする。

コマンドラインからの起動

 Windowsの標準のコマンドラインには、cmd.exeとWindows PowerShellの2つがある。そのコマンドラインからの実行を「通常起動」とする。

 また、cmd.exeには、内部コマンドとして「start」があり、これを使うとcmd.exeのコマンドラインとは異なる挙動をする。同様にWindows PowerShellには「Start-Process」コマンドがある。なお、Start-Processコマンドには、「start」というエイリアスが標準で定義されている。これをこの記事では「Start起動」と表記する。

 コマンドラインでは、プログラムの起動法法に大きく3パターンある。1つは、ファイルの拡張子までを指定したフルパス指定だ。このときは、特定の1つのファイルが指定されるので、ルールもなにもなく、ファイルがあればそれが起動される。関連付け起動があるため、多くファイルがこの形式で「起動」できる。

 もう1つは、ファイルパスは指定されているが拡張子が省略されたパターンだ。このときはPATHEXT実行が適用される。複数のファイルが一致した場合、PATHEXTに登録された順番でファイルが選択される。たとえば、コマンドラインで「C:\temp\x」を入力して、「C:\temp」に「x.exe」と「x.bat」か存在したときには、「x.exe」が起動する。というのも、PATHEXTの中で「.exe」が「.bat」よりも前にあるからだ。

 以上の動作は、通常起動でもStart起動でも同じである。最後のパターンは、パスが省略された場合だ。これは、拡張子のありなしで挙動が変わる。具体的には以下の表のようになる。この場合、「カレントディレクトリ検索」「PATH検索」「レジストリ検索」「システムディレクトリ検索」の4段階で実行ファイルを検索する。

 カレントディレクトリ検索では、ファイル名と拡張子が一致したものが起動される「一致実行」、またはPATHEXTにある拡張子だけを実行する「PATHEXT実行」に分かれる。なお、Windows PowerShellでは、カレントディレクトリにあるファイルを実行するにはパス指定が必要となる。このため通常起動ではカレントディレクトリ検索はされない。しかし、Start起動ではコマンドに一致したファイルが一致実行される。

 注意が必要なのは、cmd.exeのstart実行では、拡張子を省略したとき、一致実行を試し、その後にPATHEXT実行を試す。このため、入力コマンドがカレントディレクトリのサブディレクトリと一致した場合にディレクトリが開く。この振る舞いは通常実行では起こらない。

 カレントディレクトリに対象ファイルが見つからなかった場合、次になされるのがPATH検索だ。これは、プロセス環境変数のPATHに指定されているディレクトリを先頭から検索していく検索方法だ。

 通常のコマンドラインでは、拡張子が省略されると実行の対象になるのは、PATHEXTに指定された拡張子のみで、他の拡張子のファイルは対象にならない。しかし、start/start-processの場合、PATHEXTの拡張子が一致しなかったとき、拡張子がないファイルが「関連付け起動」される。このとき、一致すればディレクトリが開くことがある。

 通常起動では、PATH検索で対象が見つからなければエラーになるが、Start起動では、さらに「レジストリ検索」と「システム検索」が行われる。レジストリ検索とは、以下の2つのキーのサブキーに実行ファイルを登録しておくことで、起動が可能になるもの。おもにエクスプローラーからの起動などに使われる方法の1つだ。

HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\App Paths HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\App Paths

 このキーの下に実行ファイル名(拡張子を含む)でキーを作り、その既定値にファイルのパスを指定する。「レジストリ検索」は、ここから実行ファイル(拡張子省略可)を検索して、キーが存在すればそれを実行する機能だ。

 「システム検索」は、「C:\Windows」と「C:\Windows\System32」を検索するものだ。このとき拡張子が指定されていて、同名のファイルがあれば、それが「関連付け起動」される。拡張子が省略されている場合には、基本となる拡張子「.exe」「.com」「.bat」「.cmd」の4つの拡張子のみが検索対象になる。PATHEXTに登録されている他の拡張子は対象にならない。

 なお、Windows 10/11では、システム環境変数PATHにこの2つのフォルダが標準で登録されていることに注意したい。標準では、PATH検索の段階でファイルが存在すれば検索がヒットするため、システム検索まで到達しない。

 最新のWindows 11で起動ルールを調べてみたが、かなり複雑だ。実際には、これ以外にも「ファイル名を指定して実行」の機能や、APIからの起動などがある。次回はそのあたりを調べることにする。

この記事に関連するニュース

トピックスRSS

ランキング

記事ミッション中・・・

10秒滞在

記事にリアクションする

記事ミッション中・・・

10秒滞在

記事にリアクションする

デイリー: 参加する
ウィークリー: 参加する
マンスリー: 参加する
10秒滞在

記事にリアクションする

次の記事を探す

エラーが発生しました

ページを再読み込みして
ください