/ 最近 .rdf 追記 編集 設定 本棚

脳log[20180518] MeryRelay2



2018年05月18日 (金)

最終更新: 2018-06-06T13:48+0900

MeryRelay2

テキストエディタ Mery はシングルプロセス型のタブエディタだから、svn や git のコミットメッセージを編集するためには工夫が必要らしい。工夫でなんとかなるということである。

別プロセスで編集 - MeryWiki

このプラグインは C# で書かれてる。秘訣がこれ>「.NETプラグイン開発キット - MeryWiki」 DotNetLib.dll のソースが読みたいよね、ていうかこれもユーザー投稿なの?

で、プラグインを Mery2.6 の 64ビット版で試してみたんだけど、動かないのはここに書かれていた通り>「【要望】Gitの編集

再コンパイルするだけで動くんじゃないかという気もするんだけど C# はさっぱりなので、思いつきで名前付きパイプを使った方法を試してみた(プラグインもパイプも初めて!)。「プラグインソフトウェア開発キット」の C/Basic プラグインを骨組みにして必要なところだけ書き換える感じ。

.NET プラグインの方のヘルプには OnEvent を上書きするとアイドルイベントまで捕まえてしまうからできるだけ個別のイベントハンドラを実装するようにって書いてあるんだけど、C プラグインのスケルトンには OnEvent ハンドラしかなかった……。

こうなりました>MeryRelay2.zip(あとの方に新しいのがある)。64ビットコンパイラってただで手に入るのかな。Vista 時代の SDK には付属していて、それしか手元にないんだけど。

ポイントはただひとつ。PIPE_NOWAIT は罠であるということ。PIPE_WAITFILE_FLAG_OVERLAPPED を指定すれば非同期に待てる。雰囲気で PIPE_NOWAIT を指定すると待てども返ってこない。

あ、パスの区切り文字の置き換えを忘れてる(でも試したら Mery2.6は / 区切りに対応してるぽい)。それとタスクマネージャーでコマンドライン列を表示するとわかることだけど、Mery.exe のコマンドラインなのにその内容が「"MeryRelay2Exe.exe" "file.path"」みたいになってるはず。少なくとも Vista ではそう。Mery.exe が気にしてないみたいだからいいかなって、最大限に手を抜いた。そんなわけでコマンドラインは一切操作も解釈もしていないので複数ファイルのドロップもできるんだけど、どのファイルがひとつだけ選ばれて監視されるかは運です。最後にもうひとつ。短い時間で連続してリレイ経由でファイルを開くと監視が漏れるかもしれない。ていうかたぶん漏れる。バックアップ中とかウィルススキャン中だと短時間でなくても漏れるかもしれない。

結局ロックファイルでシリアライズしつつ中身で情報をやりとりするのが一石二鳥なのか? くやしいので Mutex にする。zip を差し替えておいた。これで次のようなバッチファイルにも対応する。

start "" "MeryRelay2Exe.exe" a.txt
start "" "MeryRelay2Exe.exe" b.txt
start "" "MeryRelay2Exe.exe" c.txt
start "" "MeryRelay2Exe.exe" d.txt
start "" "MeryRelay2Exe.exe" e.txt
start "" "MeryRelay2Exe.exe" f.txt
start "" "MeryRelay2Exe.exe" g.txt

無駄にクラス化するなど>MeryRelay2_class.zip<不細工な車輪を再発明してでもDLLサイズを縮めるなど。


依然こういうバッチファイルには対応しないはずだ。

start "" "Mery.exe" a.txt
start "" "Mery.exe" b.txt
start "" "Mery.exe" c.txt
start "" "MeryRelay2Exe.exe" d.txt
start "" "Mery.exe" e.txt
start "" "Mery.exe" f.txt
start "" "Mery.exe" g.txt

正しく d.txt を開いていたタブが閉じられるのを検知できるかは運次第。ここにはトレードオフがあって、これに対応しようとするとコマンドラインを解釈せざるをえないが、Mery が解釈するコマンドラインに対していかなる前提も置きたくないというのがある。それで今のように、最初に応答したタブと無差別に関係を結ぶようになってる。

ところで本家 MeryRelay.exe は最初のバッチには対応しないけど次のバッチには対応している。自分のと逆である。

 Why are HANDLE return values so inconsistent? – The Old New Thing

最初に INVALID_HANDLE_VALUE があり、その次に NULL があったと。INVALID_HANDLE_VALUE が 0 でないから、0 が有効なハンドルになることがあるのかと疑っていたが、実際のところどうなのだろう。INVALID_HANDLE_VALUE を使う関数の方が古いらしいから、ないとは言えないよね。ハンドルクラスのデフォルト値・無効値の扱いに困るんだよ。ないと言って。

INVALID_HANDLE_VALUE and NULL - Google グループ

同じ疑問を持つ人が。そして、CloseHandle を実装する側から考えてみると値が NULL で有効なハンドルはありえないでしょって答える人と、これまでの経験で問題がなかったとしてもドキュメントに沿った慎重な振る舞いを勧める人と。

俺はもちろん、問題が生じるまで単純な対処法を選ぶ>20180308

 .NET プラグインが Mery から呼ばれる方法

従来.netのDLLをアンマネージから呼び出すためにはCOMとしてレジストリ登録して、COM経由で呼び出すのが一般的ですが、当然Meryからはこのような呼ばれ方はしません。

これを解決するために、アンマネージのブリッジ用DLL(C++で書いてるみたいです)があって、これがMeryから呼ばれる。

ブリッジDLLにはMeryから呼ばれるインターフェイスがすべて実装されていて、呼ばれたらマネージDLLに転送して、そちらで目的の処理を実行。 という手順をとっているようです。

「再コンパイルするだけで動くんじゃないかという気もする」とは書いたけど .Net には CPU を限定しない AnyCPU ビルドというのがあるらしく、ks さん本人のものと思われるブログでもそれが言及されていた。なのにどうして 32ビット版限定プラグインになってしまうのかな、と。その種明かし。

MeryRelay プラグインには MeryRelay.dll (160 KB) と MeryRelay/MeryRelay.dll (6 KB) という2つの同名の DLL ファイルが含まれていて、たぶん大きい方がアンマネージドのブリッジであり、32 ビット版 Mery からプラグインとして見えるもの。

svn 連携、git 連携にしろプラグイン作成にしろ、いろいろ方法があるもんですね。