LoginSignup
6
5

More than 5 years have passed since last update.

x64 Windows で Poderosa のターミナルをタブで次々と開く方法(調査編)

Last updated at Posted at 2014-08-25

たくさんのサーバに一挙ログイン!してたのに・・・

Windows7(x86)からWindows8.1(x64)にアップグレードしたら、Poderosaの「-open」オプションを使ってひとつのPoderosaプロセスで複数のタブが起動できなくなった。

元々batファイルで以下の様に指定してた。
D:\soft\Poderosa に Poderosa本体がインストールされています
D:\soft\Poderosa\gts に gtsファイルが複数置いてあります

とあるディレクトリにあるgtsファイルを読み込んで一気に開くbatファイルは以下の通り用意してました

poderosa_up.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"の引数を処理しているところのソース追いかけてみた。

Plugin\PoderosaStartup.cs
            //コマンドライン引数を読む
            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()が何らかの理由で上手くいってないに違いない。
さらに調査を進めると・・・

Plugin\PoderosaStartup.cs
        //別インスタンスへの送信を試みる。ショートカットを開いたときの多重起動に関するところで。
        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()ではウィンドウが見つからないため、新規に起動されていたわけですね。

やっと挙動に納得。次は対応策を検討せねば。。。

6
5
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
5