WSLって歴史的経緯で今も bash.exe
で起動ができるけど、 bash.exe
で起動したときは chsh
で設定されたシェルではなく常にbashが起動してしまう。たぶん内部的に /usr/bin/bash
を実行してるんだとおもう*1。
wsl
を呼べば chsh
で設定されたシェルが起動はするのだけどせっかくなので zsh.exe
を起動するとデフォルトのWSL環境でzshが実行されるようなやつを作ってみました。
やっていることはarg[0]
からファイル名を取り出して拡張子を除去、引数部分は無加工のまま受け取ってそれらをくっつけてWSLプロセスを起動。
実行ファイルの名前を変えると*2起動するWSLプロセスが変わる仕組みです。busyboxみたいな挙動ですね。
せっかくなのでWSLでプロセスを起動したりすることについて残しておきます。
WSL内でのプロセスの実行
WSL内でプロセスを実行するには大昔は非公開APIをCOM経由で呼ばないといけなかったのだけど、いまではちゃんと公開APIが用意されているのでそれを呼ぶだけ。
プロセスの実行方法は2種類用意されていて
- 標準入出力をパイプで渡してhProcessを返すパターン
- 現在実行中のプロセスの標準入出力を使ってプロセスが終了するまでAPIが返ってこないパターン
コンソールを持たないプロセスの場合とかは前者、コンソールでWSLプロセスが終了するまで制御を返さなくていいなら後者でいいと思う。
今回の場合は単純にWSL内でプロセスが実行できて終了すれば自分自身も終了するので後者。
このAPIに、実行したいディストリビューションの名前、実行したいパスなどを指定するだけでWSLでプロセスが実行できるとても簡単。
ひとつ問題があって、ドキュメントには wslapi.lib
をリンクせよ。と書いているのだけどこれがSDKになぜか含まれていない。なぜ含まれていないのかは謎だけど、実際なぜか含まれていない。
しかたないので、wslapi.dll
をダイナミックリンクして使いましょう。
デフォルトディストリビューションの解決
ドキュメントを見てもデフォルト設定のディストリビューションがどれなのかを取得することはどうやらできなさそうです。これはレジストリを見ると解決できます。
WSLに関する設定は HKEY_CURRENT_USER\SOFTWARE\Microsoft\Windows\CurrentVersion\Lxss
配下に収まっています。ここの、DefaultDistribution
に書き込まれている名前でサブキーをたどると
そこにデフォルト設定になっているディストリビューションの情報が埋まっています。
WslLaunch*
はディストリビューションの名前を必要としているので、サブキーから DistributionName
の値を読むことでデフォルト値が解決できます。
おしまい
こんな感じでWSLのプロセスがWindows側から起動できるそうです。
zshが起動したいためだけに作ったけれども、python.exeとかgrep.exeとか用意したらなかなか楽しくなってきた。