たくさんのサーバに一挙ログイン!してたのに・・・
Windows7(x86)からWindows8.1(x64)にアップグレードしたら、Poderosaの「-open」オプションを使ってひとつのPoderosaプロセスで複数のタブが起動できなくなった。
元々batファイルで以下の様に指定してた。
D:\soft\Poderosa に Poderosa本体がインストールされています
D:\soft\Poderosa\gts に gtsファイルが複数置いてあります
とあるディレクトリにあるgtsファイルを読み込んで一気に開くbatファイルは以下の通り用意してました
set PODEROSA_ROOT=D:\soft\Poderosa\
set PODEROSA_GTS=D:\soft\Poderosa\gts\
set PODEROSA_EXE=%PODEROSA_ROOT%Poderosa.exe
set PODEROSA_CONF=%PODEROSA_GTS%conf
start "Poderosa" /D %PODEROSA_ROOT% %PODEROSA_EXE%
Rem 以下の2秒は環境による。ウィンドウができ終わるまで待つのがみそ。
timeout 2
Rem dirかまして*.gtsを全部PoderosaでOpenする!
for /f %%i in ('dir /b %PODEROSA_GTS%*.gts') do "%PODEROSA_EXE%" -open "%PODEROSA_GTS%%%i"
でも、これがWindows8.1(x64)に移行したら動かなくなりました。。。
batファイルは動くのですが、gtsファイルの分だけPoderosa.exeが起動してしまい
タブにならず、たくさんのウィンドウが表示されるようになってしまいました。
当初は、Windows7からWindows8.1に移行したためだと考えていたのですが、調査したところx86からx64になったため挙動が変わったって事だったのですが、気がつくまでの顛末を書いておきたいと思いました。
Poderosaのソースをみてみる
とりあえず"-open"の引数を処理しているところのソース追いかけてみた。
//コマンドライン引数を読む
int i = 0;
while (i < args.Length) {
string t = args[i];
string v = i < args.Length - 1 ? args[i + 1] : "";
switch (t) {
case "-p":
case "--profile":
preference_home = ResolveProfileDirectory(v);
i += 2;
break;
case "-a":
case "--addasm":
pm.AddAssembly(home_directory, v.Split(';'));
i += 2;
break;
case "-r":
case "--remasm":
pm.RemoveAssembly(home_directory, v.Split(';'));
i += 2;
break;
case "-open":
open_file = v;
i += 2;
break;
default:
i++;
break;
}
if (open_file != null && TryToSendOpenFileMessage(open_file))
return null; //別インスタンスに送信
ふむふむ。。。どうやら、TryToSendOpenFileMessage()が何らかの理由で上手くいってないに違いない。
さらに調査を進めると・・・
//別インスタンスへの送信を試みる。ショートカットを開いたときの多重起動に関するところで。
private static bool TryToSendOpenFileMessage(string filename) {
//ウィンドウを見つける
unsafe {
//find target
IntPtr hwnd = Win32.FindWindowEx(IntPtr.Zero, IntPtr.Zero, null, null);
char[] name = new char[256];
char[] mf = new char[256];
while (hwnd != IntPtr.Zero) {
int len = Win32.GetWindowText(hwnd, name, 256);
if (new string(name, 0, len).IndexOf("Poderosa") != -1) { //Window Classを確認するとか何とかすべきかも、だが
if (TryToSendOpenFileMessage(hwnd, filename))
return true;
}
hwnd = Win32.FindWindowEx(IntPtr.Zero, hwnd, null, null);
}
return false;
}
}
原因は64bitプロセス内でWin32 APIのFindWindowEx()を使っても64bitプロセスのウィンドウは見つからないこと!
ここのソース【Win32.FindWindowEx】を見たときに「ああ、OSのバージョンじゃなくて、x86をx64にしたせいだ!」ってひらめきました!
ちょっと調べるとたくさん出てくる出てくる。
● 32bit プロセスは 64bit プロセスを見つけられない - Life like a clown
.Net Frameworkで動くPoderosaは64bitで動いているので、Win32 APIであるFindWindowEx()ではウィンドウが見つからないため、新規に起動されていたわけですね。
やっと挙動に納得。次は対応策を検討せねば。。。