MicrosoftはWindows 10にLinuxバイナリを実行するための機能WSL (Windows Subsystem for Linux)を導入し、これに合わせてコンソールの改善にも取り組んできた。しかし、現状は必要なものは満たしていると言えるが、満足できるものとは言い難いことをこれまで何度か指摘してきた。その対応策として、本連載の第111回ではコンソールアプリケーションとして「ConEmu」を利用する方法を紹介したこともある。
そんななか、なぜWindowsのコンソールアプリがLinux系のターミナルアプリケーションと比べて使いにくいのかを知る手がかりが、Microsoftから「Windows Command-Line: Inside the Windows Console」として公開された。Windowsのコンソールがどういった作りになっており、現在は何が課題になっているのかといった辺りが説明されている。Windowsにおけるコンソールアプリケーションの動きを知る上でも参考になるので、今回はこの解説記事からポイントをピックアップして紹介しよう。
コンソールアプリケーション ConHost.exe
ターミナルを好んで使うユーザーであれば、macOSなら「iTerm2」、Ubuntuなら「GNOME Terminal」といったように、お気に入りのターミナルアプリケーション(ターミナル、ターミナルエミュレータとも呼ばれる)がある。ターミナルアプリケーションごとに特徴があり、癖も違うので、こだわるユーザーは自分の好みのアプリケーションを見つけてそれを使うようになる。
Windowsの場合はWindowsコンソールがターミナルアプリケーションと同様のポジションにあるのだが、Windowsではコンソールそのものを実行するという感覚が薄い作りになっている。しかし、実際にはコンソールと、コマンドプロンプトやPowerShellは別のアプリケーションとして実装されている。
「Windows Command-Line: Inside the Windows Console」では、この仕組みをわかりやすく示している。次の画像を見てほしい。
Windows 10では図の左側にある「ConHost.exe」というアプリケーションがコンソールとして動作する。これがいわゆるiTerm2やGNOME Terminalに相当するアプリケーションということになる。図の右側にある「Command-Line App」という部分がコマンドプロンプトやPowerShellに相当する。WSLもここに該当する。ConHost.exeとCommand-Line Appは「ConDrv」と呼ばれるカーネルドライバを通じて通信して動作する仕組みになっている。
例えば次のようにConHost.exeだけを実行してみると、コンソールが起動することを確認できる。
では「ConHost.exe」を実行すると何が見えるのかというと、次のようにコマンドプロンプトの実行を確認できる。Command-Line Appが指定されていない場合、自動的にコマンドプロンプトを実行してConHost.exeに接続する仕組みになっているためだ。macOSやLinuxで新しくターミナルを起動するとデフォルトシェルであるbashが動作するようなものだと思えばよいだろう。
本連載は技術詳細を解説するものではないので詳しい説明は省くが、WindowsではほかのWindowsアプリケーションとの互換性や一貫性という観点から、UNIX系のターミナルアプリケーションが実装しているようにテキストストリームを実装するという方法をとらず、コンソールAPIを提供するといった仕組みを採用してきた。WindowsでUNIX系のコマンドやユーティリティを移植するにはコンソールAPIを使えばよいわけだが、このAPIはWindowsのエコシステムのなかで使われているもので、Windows以外では使われていない。そのため移植は活発には進まなかった。
サードパーティ製のコンソールはどうしてるのか
しかし、Windowsには先に取り上げたようにすでにコンソールとして機能するサードパーティ製(Microsoft以外のソフトウエアという意味)のコンソールが存在している。ConEmuはそうしたアプリケーションの1つだし、解説記事ではConEmu以外にもCmder、Console2/ConsoleZ、Hyper、Visual Studio Code、OpenSSHなどのコンソールを紹介している。これらアプリケーションと同じようにConHostも実装すればよいだけのように思えるが、記事中ではこうしたサードパーティ製アプリケーションでは通常あまり使われないようなトリックを使ってコンソールとして動作するように「振る舞っている」のだと指摘している。
例えば、こうしたサードパーティ製コンソールではコマンドラインアプリを座標(-32000,-32000)といったまず表示されることのない場所に起動し、こうした見えない場所のコンソールへキーストロークを送信、そしてそのコンソールの出力結果をキャプチャして自身の見えているスクリーンへ再描画するといった手段を取っているという。かなりクレイジーな方法だが、こうしたサードパーティ製コンソール開発者の「コンソールとして動作させる」という意思と独創性を示す物だと賞賛されてもいる。
ConHostの今はどうなっているのか
それでは現在のConHostの実装はどうなっているのだろうか。UNIX系のターミナルアプリケーションがそうであるように、ANSI/VTシーケンスの実装を進めたことでUNIX系のコマンドがそのまま利用できる状態になっている。まだいくつか実装や変更が必要になる部分は見られるが、最低限必要なところは押さえているといった状況だ。
記事では現在の課題としてユニコード関連の実装も挙げている。提供されているWindowsのAPIは現在のユニコードエンコーディングが普及する前のAPIであり、今後この部分の開発を進める必要があると指摘している。
ConHostの興味深いところは、コマンド履歴の機能をAPIとして提供している点にある。UNIX系コマンドではコマンド履歴の機能はインタラクティブシェルが個々に実装している。Microsoftではこの部分の機能をコンソールConHostの機能として提供することで、Command-Line App側が個別に実装する必要性をなくそうとしている。つまり、将来的にはPowerShellとコマンドプロンプトで共通のコマンド履歴機能を使えるようになるかもしれないというわけだ。
今のところConHostの提供している機能は、特にユーザーの操作性に関する部分では以前から使われているターミナルアプリケーションには今一歩届かない感が否めない。だが、MicrosoftはConHostに関する開発に取り組んでおり、今後も改善が期待できるというのが今回、本連載の読者が得られる最大のポイントではないだろうか。
今しばらくはサードパーティ製コンソールのほうが便利な状況が続くのではないかと思うが、タブUI/UX機能の導入やコンソールレベルでのコマンド履歴機能などが動作するようになってくると、ConHostも魅力的になってくるはずだ。この辺りは今後のアップデートで定期的に取り上げていく。