F1大好きな、インチキ技術者の日記

F1大好きなインチキ技術者が情報を発信して、自分を変えようとしている日記です

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

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

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

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

とあるディレクトリにある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()ではウィンドウが見つからないため、新規に起動されていたわけですね。

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

*1:2014年08月22日にQiitaに投稿した記事です。

ApacheでQueryString(URLパラメータ)の値によってBASIC認証をかけたい!

Apacheで特定のQueryString(URLパラメータ)に応じてBASIC認証をかける必要が出てきたのでRewriteを用いて対応しました。*1

設定したいこと

  • 「area=admin」がQueryStringに設定されている場合BASIC認証をかける。
  • 「area=admin」がない場合はそのまま表示できる。

当初は、 SetEnvIf を用いていけるかな?と考えていたけど、SetEnvIf の REQUEST_URIにはQueryStringは含まれていない。

「むー、こまった。」と途方に暮れていたらQueryStringを扱うにはRewriteを使いなさいと書いてあったので早速検討した。

「なんでBASIC認証かけるのにRewriteなんだよ。。。」ってブツブツ言いながら以下の設定をApacheに追加したら思ったとおりの挙動となりました。

Apacheの設定

RewriteEngine On
RewriteCond %{QUERY_STRING} area=admin
RewriteRule (.*) $1 [E=admin_access:1]

<Location />
    Order allow,deny
    Allow from All
    Deny from env=admin_access
    
    AuthUserFile /etc/httpd/conf/.htpasswd
    AuthGroupFile /dev/null
    AuthName "Administorator's Area"
    AuthType Basic
    require valid-user
    
    Satisfy Any
</Location>

やっぱり、ちょっと違和感あるな。。。(^_^) ほかに方法ないのかな~

参考にさせていただいたサイト

まとめサイト: SetEnvIf の Request_URI には Query String は含まれない wall-climb » 特定URLのみBASIC認証を除外する

*1:2014年08月22日にQiitaに投稿した記事です。

プライバシーポリシー・問合せ