トップ «前の日記(2006-10-27) 最新 次の日記(2006-10-29)» 編集

日々の破片

著作一覧

2006-10-28

_ NETアプリケーションにリモートオートメーションを付ける

必要がでてきて、ちょっと考えた。

たとえば、定期的に何かする静かなアプリケーション(UIと言えばタスクバーの通知領域にアイコンがあって、たまに「エラーになってるからログ見てくれ」とか吹き出しが出る程度のやつ)が今何してるか知りたいとする。

クライアントは、HTAとかだよな、やっぱり、と考える。

すると逆向きCOM Interopってのが候補に挙がる。

が、なんか違う気がする。大体、後からノートPCをHubに差し込んで調べるというようなこと考えると、危険極まりないDCOMの利用になってしまう。それは、最悪の場合に最悪の事態となる。

ではRemotingって……相変わらずVisual Studioのサポートないのか。却下だ。

Webサービス……「追加」からは選べないな。

で、System.Net.HttpListenerを使うことになる。

使い方は簡単。送信情報に秘匿すべきものがなければ、ほとんど何も考える必要すらない。エフェメラルポートの衝突は怖いけど(ないわけじゃないんだな、これが)、まあ、多少のリスクは抱えてもしょうがないと割り切る。(追記:80でも良いのだがなんとなく別にしたい)

ただ、ワーカースレッドとか勝手に作ってくれないし、基本は一発勝負型なので自分で再要求したりしないといけない。最初、ちょびっとはまった。(続く)

_ 常駐するプログラム例

たとえば、こんなプログラムを作るとする。
10秒ごとにカウンターは増えるが外側から知る術がない。
っていうか、終わらせることもできない(終わらせるための準備はできているけど)。
using System.Threading;
public class Counter
{
    volatile bool stop;
    volatile int counter;
    public void Service()
    {
        while (!stop)
        {
            counter++;
            Thread.Sleep(10000);
        }
    }
     
    public static void Main()
    {
        Counter c = new Counter();
        c.Service();
    }
}
このプログラムが、外部のプログラムに現在のカウンター値を教えるようにできることと、いざとなったらきれいに終わらせられるようにすることがやりたいことだ。

_ HttpListenerによる外部インターフェイスの提供

というわけで、HttpListenerを使う。それにしても無名メソッドが使えるおかげでいちいちハンドラに無用な参照を与える必要がなくなったのは大いに結構なことだ。
using System;
using System.IO;
using System.Net;
using System.Text;
using System.Threading;
public class Counter
{
    volatile bool stop;
    volatile int counter;
    volatile HttpListener listener;
    public Counter()
    {
        listener = new HttpListener();
        listener.Prefixes.Add("http://*:9020/counter/");
        listener.IgnoreWriteExceptions = true;
        listener.Start();
        Listen(); // 再実行するので別メソッドにしておく
    }
    void Listen()
    {
        listener.BeginGetContext(delegate (IAsyncResult ar)
         {
             if (stop)
             {
                 return;
             }
             Listen(); // 次のリクエストを受け付けるようにする
             HttpListenerContext lc = listener.EndGetContext(ar);
             lc.Response.ContentType = "text/xml";
             TextWriter w = new StreamWriter(lc.Response.OutputStream,
                                             Encoding.UTF8);
             w.WriteLine("<?xml version=\"1.0\"?>");
             w.WriteLine("<Counter>");
             w.WriteLine("  <value>" + counter + "</value>");
             w.WriteLine("</Counter>");
             w.Close(); // MSDNのサンプルだとCloseを呼んでるので真似。
             if (lc.Request.Url.Segments[lc.Request.Url.Segments.Length - 1]
                 == "quit") // C#とJavaの最大の差
             {
                 stop = true;
             }
             lc.Response.Close();
         }, this);
    }
    public void Service()
    {
        while (!stop)
        {
            counter++;
            Thread.Sleep(10000);
        }
        listener.Stop();
    }
    
    public static void Main()
    {
        if (!HttpListener.IsSupported)
        {
            Console.WriteLine("Buy Windows XP SP2 Now !!!");
            return;
        }
        Counter c = new Counter();
        c.Service();
    }
}
これで、http://localhost:9020/counter と呼べば現在のカウンター値を参照できるし、http://localhost:9020/counter/quit と呼べば実行を終了できる(最大10秒待たされるけど)。
なお、ここではHTAをクライアントとして想定しているから、VBScriptで手軽に扱えるtext/xmlを返しているが、jsonとかでも良いとは思うし、open-uriを想定すればYAMLというてもある。
本日のツッコミ(全2件) [ツッコミを入れる]
_ きしだ (2006-10-28 05:05)

JMX使うのが一番便利かな〜と。

_ arton (2006-10-28 10:25)

サンプルソースきぼんぬ。


2003|06|07|08|09|10|11|12|
2004|01|02|03|04|05|06|07|08|09|10|11|12|
2005|01|02|03|04|05|06|07|08|09|10|11|12|
2006|01|02|03|04|05|06|07|08|09|10|11|12|
2007|01|02|03|04|05|06|07|08|09|10|11|12|
2008|01|02|03|04|05|06|07|08|09|10|11|12|
2009|01|02|03|04|05|06|07|08|09|10|11|12|
2010|01|02|03|04|05|06|07|08|09|10|11|12|
2011|01|02|03|04|05|06|07|08|09|10|11|12|
2012|01|02|03|04|05|06|07|08|09|10|11|12|
2013|01|02|03|04|05|06|07|08|09|10|11|12|
2014|01|02|03|04|05|06|07|08|09|10|11|12|
2015|01|02|03|04|05|06|07|08|09|10|11|12|
2016|01|02|03|04|05|06|07|08|09|10|11|12|
2017|01|02|03|04|05|06|07|08|09|10|11|12|
2018|01|02|03|04|05|06|07|08|09|10|11|12|
2019|01|02|03|04|05|06|07|08|09|10|11|12|
2020|01|02|03|04|05|06|07|08|09|10|11|12|
2021|01|02|03|04|05|06|07|08|09|10|11|12|
2022|01|02|03|04|05|06|07|08|09|10|11|12|
2023|01|02|03|04|05|06|07|08|09|10|11|12|
2024|01|02|03|

ジェズイットを見習え