WSL2の中からWindows側のブラウザを開く

GitHub CLIHeroku CLIなど、ブラウザを自動で開いて認証させるタイプのCLIが最近増えています。

普通に使う分には便利なのですが、WindowsのGUIアプリ+WSL2という環境では、WSL2の中からWindows側のブラウザを開くことができなくて一手間かかることがあります。

最近はWSLgを使ってすべてをWSL側で完結させるという手もあるでしょうが、今の自分の開発のスタイルでは、CLIのツールはすべてWSL2、GUIツールはWindows側に入れるようにしています。そのため、上記のような問題がおきることが度々あり困っていました。

今はこれを解決するために

  1. xdg-openを入れる
  2. Windows側のブラウザを開くデスクトップエントリを作る
  3. xdg-openのdefault-web-browserに2で作ったデスクトップエントリを登録する

という方法を使っています。

1. xdg-openを入れる

WindowsでいうstartやMacOSでのopenのように、引数に応じていいかんじにデスクトップアプリケーションを起動するためのエントリポイントとなるツールがxdg-openです。(実際にはシェルスクリプト)

xdg-openまたはxdg-utilsというパッケージに入っていることが多いのでこれをインストールします。Gentooならemerge xdg-utilsでOKです。

2. Windows側のブラウザを開くデスクトップエントリを作る

デスクトップエントリというのは、Linuxにおけるアプリケーションやディレクトリへのショートカットのことです。

詳しくは信頼と実績のArchWiki デスクトップエントリ - ArchWiki をどうぞ。Linuxデスクトップであれば、デスクトップの画面上にならぶアプリケーションの起動ショートカットの実態がこれになります。

ユーザ単位のデスクトップエントリは ~/.local/share/applications/に置くことになっているので、ここにWindowsのEdgeを起動するデスクトップエントリを作成します。中身はこんなかんじ。

[Desktop Entry]
Encoding=UTF-8
Version=1.0
Type=Application
NoDisplay=true
Exec=/mnt/c/Users/kenchan/AppData/Local/Microsoft/WindowsApps/MicrosoftEdge.exe
Name=Edge
Comment=Microsoft Edge

Execに指定するパスは、which MicrosoftEdge.exe などで調べればよいです。

さて、だったらここでstartexplorer.exeを指定すれば、Windows側のデフォルトブラウザの変更を反映していいかんじになるんじゃないの?と思った人、鋭いですね。

ただ、以下のような理由でそれではうまくいきません。

  • startはアプリケーションではなくWindowsのコマンド(?)なので、WSL側から実行するにはcmd.exeを経由したりしないといけない
  • explorer.exeはアプリケーションを開けても終了コードが0(正常)にならないため、xdg-openとの相性が悪い。

xdg-openでブラウザを判定して開く処理は scripts/xdg-open.in · master · xdg / xdg-utils · GitLab にあります、この関数の呼出元を見てもらうとわかるのですが、ざっと説明すると「ブラウザっぽいコマンドを優先順位を決めて並べて、それを順番に叩いて正常終了したらそこでおわり」という大味な実装になっています。

そのため、explorer.exeを指定したデスクトップエントリを作った場合、たしかにブラウザは開くのですが、警告のメッセージが大量にでてきたり、同じページをブラウザで何回も開かれたりということがおきます。

上記の理由から、今のところ私はデフォフトブラウザとして使っているEdgeを直接開くデスクトップエントリを使っています。

3. default-web-browserとして設定する

xdg-openにURLを渡したときに開くアプリケーションを指定する方法は2つあります。

  • 環境変数 BROWSER にコマンドを指定する
  • xdg-settingsdefault-web-browserにデスクトップエントリを指定する

今回は下の方法を使います。上の方法を使うのであれば実は今書いているようなことは一切必要なく、BROWSER=MicrosoftEdge.exeで終わりです。しかし、dotfilesを他環境と統一している場合は分岐を入いれるか、/etc/environments.dをいじるかになり、ちょっと嫌だなと思って、こちらの方法にしています。

xdg-settingsで設定するには以下のようなコマンドを打てばOKです。edge.desktopの部分は、2でつくったデスクトップエントリのファイル名を指定します。

# setで設定
$ xdg-settings set default-web-browser edge.desktop

# getで確認
$ xdg-settings get default-web-browser

設定ができたらxdg-open https://google.comなどでWindows側のブラウザが開くことを確認しましょう。

これで、CLIの中からいきなりブラウザが起動されることがあっても大丈夫です。よかったですね。

おまけ

こんなことをしなくても、 4U6U57/wsl-open: Open files with xdg-open on Bash for Windows in Windows applications. Read only mirror from GitLab, see link を入れればよかろうというのはそうです。はい。