• コマンドラインは行方不明

PowerShell 7.4で「Command-Not-Found」が利用可能になった。これは、コマンドが見つからなかったときに、Wingetによる適切なプログラムのインストールなどを提案するものだ。当初、この機能は、PowerToysの機能としてRelease v0.77.0(2024年1月10日)に搭載された。そのためのインターフェースとなるフィードバックプロバイダ(FeedbackProvider)は、昨年3月に公開されたPowerShell v7.4.0-preview 2に搭載された。

現在の安定版はPowerShell v7.4.2(Windows PowerShellではない)である。現在の安定版では、PowerToysからの機能有効化も可能だが、PowerToysをインストールしなくても、Wingetがインストールされていれば、Command-Not-Foundを有効化できる。

まずは、以下のコマンドで、「Microsoft.WinGet.CommandNotFound」モジュールをインストールする。


Install-PSResource -Name Microsoft.WinGet.CommandNotFound

Install-PSResourceコマンドの実行後は、自動的にモジュールがインポートされるのですぐに利用できる。しかし、以後のセッションでも常にCommand-Not-Foundを使えるようにするには、PowerShellの起動時にモジュールをインポートする必要がある。それには、PowerShellのプロファイル($PROFILEで参照可能)に以下のコマンドを手動で入れておく必要がある。


Import-Module -Name Microsoft.WinGet.CommandNotFound

なお、最新のPowerToys(V0.81.0)は、上記と同じモジュールを組み込む。しかし、旧版では、PowerToysに含まれているモジュールWinGetCommandNotFound.psd1(内部でPowerToys.CmdNotFound.dllの組み込みを指定)を組み込む。このとき、PowerShellのプロファイルに注釈行とImport-Moduleコマンドを追加する。場合によっては、このPowerToys旧版の指定が残ることがある。PowerToysのImport-Moduleコマンドは前後に注釈がある。同じImport-Moduleコマンドだが、前後の注釈がないとPowerToysのCommand-Not-Found機能は、未インストールと判断してしまう。2回実行してもエラーにはならず実害はないが、PowerToysを使うなら、手動で設定せず、PowerToysのCommand Not Foundの設定でインストールする方がいいだろう。

この機能を有効化すると、コマンドが見つからない場合に、エラーメッセージに続いて、WinGetを使ったコマンドインストールの提案が行われる。ただし、提案はあくまでもコマンド名でのみ行われるため、必ずしも正解とは限らない。また、Wingetのパッケージを前提にしているため、Microsoftストアの一部と、Wingetリポジトリに登録されているパッケージに限られる。

PowerShellに限らず、一般にシェルは、Path変数など、実行ファイルへのパスが定義されていないとコマンドを見つけることができない。このため、インストールされていてスタートメニューから起動可能でも、Path変数にパスが設定されていないコマンドは、Command not foundエラーになることに注意されたい。

PowerShellの実行中にF2キーを使って、予測IntelliSenseのListViewを有効にしておくと、コマンドの補完候補に、Command-Not-Foundの提案が含まれるようになる。たとえば、エラーのためwingetコマンドが提案されたあと、コマンドラインにwinと入力すれば、提案されたwingetコマンドが補完候補として表示される(写真01)。ここでは上下カーソルキーを使ってコマンドの選択ができる。この機能により、エラーの直後にコマンドラインの補完機能でインストールのためのwingetコマンドを起動できる。

  • 写真01: PowerShell v7.4.0-Preview.2以前にはPSCommandNotFoundSuggestionという機能があった。これは、エラーのときに簡易な提案をしていた(最初のコマンドとその応答)。写真の2つ目のコマンドでMicrosoft.WinGet.CommandNotFoundを組み込むと、Wingetを使った提案を行うようになる(3つ目のコマンドとその応答)。F2キーで予測IntelliSenseを表示させると、補完候補に提案したWingetコマンドが表示される(4つ目のコマンド)。これは上下カーソルキーで選択してEnterキーで補完を完了できる

なお、PowerShell v7.4のCommand-Not-Foundは、GitHubでソースが公開されている。

実は、同名の機能がLinuxのbashにある。WSLにもあるUbuntuなどいくつかのディストリビューションでは、標準でこれが有効になっている。Command Not Foundエラーのとき、aptパッケージマネージャーのコマンドで提案を行う。この機能は、2010年前後、bash Ver.4あたりから導入されたと記憶する。

bashでは、command-not-found-handlerと呼ばれる関数を定義することで、コマンドが見つからないときのエラー処理を定義できる。現在のUbuntuには、標準でインストールされるcommand-not-foundというパッケージがあり、ここでこの関数を定義している。現在のUbuntuでは、このあたりの処理は、/etc/bash.bashrcの中に記述されている。

PowerShellのCommand-Not-Foundは、PSReadlineなどと同じく、Linux/bashの機能に「インスパイア」されたものなのである。

今回のタイトルネタは、1965年のモノクロ映画「バニー・レークは行方不明」(Bunny Lake Is Missing)である。ネタバレになるので中身については何も言わないが、主演女優のキャロル・リンレイ(Carol Lynley)は、のちに「ポセイドンアドベンチャー」(1972年。The Poseidon Adventure)で最後まで生き残る歌手役を演じた。1970年台、日本でも放映されていた米国のテレビドラマのゲストとしてときどき見かけた。映画「2001年宇宙の旅」(1968年。2001: A Space Odyssey)で、ディスカバリー号の船長を務めたキュア・デリア(Keir Dullea)も出演している。