.exeファイル(Windows用とMono/.NET用)の識別と関連付けについて
NautilusなどのGUIファイルマネージャやbinfmt_misc(関連記事)ではファイルの種類に応じてそれを開いたときに、関連付けられたアプリケーションに引数としてそのファイルを渡すことができる。しかし、.exeファイルの場合
と複数の可能性があるため、直接どちらかに関連付けをしてしまうともう片方では使えない。
fileコマンドでWindows向け実行ファイルとMono/.NETアセンブリを識別可能
ファイルを識別するfileコマンドはファイル先頭にある種類ごとに固有の文字列「マジック」で大まかなファイルの識別をするだけでなく、種類によっては更に深い情報を調べて表示してくれる。
幸いなことに、バージョン4.26の時点のfileコマンドでは、Windows向けの実行ファイルとMono/.NETアセンブリとを識別してくれる。
(Windows向けの実行ファイル) $ file [.exeファイルの場所] [.exeファイルの場所]: PE32 executable for MS Windows (GUI) Intel 80386 32-bit (Mono/.NETアセンブリ) $ file [.exeファイルの場所] [.exeファイルの場所]: PE32 executable for MS Windows (console) Intel 80386 32-bit Mono/.Net assembly
種類によって処理を振り分ける
コマンドの出力という形でどちらの形式かが得られるということから、下のようなシェルスクリプトを作成してこれに関連付けを行うことにより、種類に応じたアプリケーション(WineかMono)で.exeファイルを開くということが可能になる。
下のコードを使用するにはfileコマンドを使用するのでこれがパッケージ(「file」というパッケージ名が多い)としてインストールされている必要がある。なお、このコードはCC0のもとで公開する。
[任意]ファイル名: exehandler ライセンス:CC0
#! /bin/bash PATH=/bin:/usr/bin IFS= FILE="$(file "${1}")" [[ "${FILE:${#FILE}-18}" = "Mono/.Net assembly" ]] && CMD=mono || CMD=wine ${CMD} ${@}
fileコマンドでMono/.NETアセンブリを渡したときに出力の最後に出る文字列が「Mono/.Net assembly」であるという前提なので、今後この表記が変われば4行目をそれに合わせて修正する必要が出てくる。「18」の部分はその文字列長となるため、長さが変わったりした場合はそこも変更することになる。
なお、「Windows用の.NET FrameworkをWineにインストールしてMonoは使わない」ということもできなくはないかもしれないが、Windowsの機能を呼び出している.NETアプリケーションに対して使用するのを除いておすすめはできない。
下はNautilusに関連付ける例*1。場所は実際の配置場所に合わせる。画像では/usr/local/bin/以下に(管理者権限で)保存した場合となる。
binfmt_miscでの使い方としては
(管理者権限のシェル上) # echo ':EXE:M::MZ::/usr/local/bin/exehandler:' > /proc/sys/fs/binfmt_misc/register (一般ユーザでsudoを使用) $ sudo sh -c "echo ':EXE:M::MZ::/usr/local/bin/exehandler:' > /proc/sys/fs/binfmt_misc/register"
のようになる。こちらもexehandlerの場所は実際の配置場所に合わせる。
「C#のテストを兼ねた静的メンバのテスト」で書いているコードをビルドしたアセンブリを下のように実行すると
$ [Hello.exeの場所] AAA BBB CCC Hello, Work! arg:AAA arg:BBB arg:CCC TestClass(): cnt=1 str=aaa (以下略)
となり、引数も渡されていることが分かる。
関連記事:
使用したバージョン:
- file 4.26
- Nautilus 2.24.0
*1:コンテキストメニュー「別のアプリで開く...」から出るダイアログで設定