ファイルを開くプログラムの選択ダイアログに表示されなくなったら

 Windows XPだと、ファイルの関連づけがされていないファイルをダブルクリックしたときに、そのファイルを開くプログラムを選択するためのダイアログが表示されます。ここから関連づけも出来るし、一時的に開くだけというのも出来て便利なので、私は多用しています。

 ところが、このダイアログに選択したいプログラムが表示されなくなることがたまにあります。あったはずのプログラムを参照ボタンを押して選択し直しても、リストに表示されないのです。

 どうやらこの現象は、そのプログラムのインストールパスを変えてしまった場合に発生するようです。(例えばc:\vim7→c:\vimに変更など) なぜかよくやってしまうので、そんな場合の対処法をメモしておきます。

 まず、レジストリエディタを起動し、HKEY_CLASSES_ROOT\Applicationsを開きます。この中に該当プログラムのファイル名(gvim.exeなど)のエントリがあるはずなので、それを見つけ出します。見つかったら、そのエントリ名を書き換えます。削除しても良いはずですが、何かあった時に戻しやすいように私はいつもリネームしてます。もちろん、それでもレジストリが壊れる可能性はあるので、当然自己責任でお願いします。

 該当エントリをリネームすると、ファイルを開くプログラムの選択ダイアログで、参照ボタンを押してプログラムがリストに追加できるようになります。後は、リストからプログラムを選べば、ファイルが開けるようになります。

ポートを開いているプロセスを特定する

使いたいと思ったポートが何者かに使われていたとき、どのプロセスが使ってるのか知りたいってことありますよね。そんなときは、netstatに-oオプションをつけるとプロセスIDを表示してくれるようになるらしいです。例えば、以下のようにして調べられます。ちなみに-aは全部表示、-nはアドレスとポートを数値形式表示のオプションです。

一番右側のPIDのところに出てくるのがプロセスIDになります。

C:\>netstat -nao

Active Connections

  Proto  Local Address          Foreign Address        State           PID
  TCP    0.0.0.0:135            0.0.0.0:0              LISTENING       1064
  TCP    0.0.0.0:389            0.0.0.0:0              LISTENING       124
  TCP    0.0.0.0:445            0.0.0.0:0              LISTENING       4
  TCP    0.0.0.0:515            0.0.0.0:0              LISTENING       1404
  TCP    0.0.0.0:2030           0.0.0.0:0              LISTENING       292
  TCP    0.0.0.0:3306           0.0.0.0:0              LISTENING       2008
  TCP    0.0.0.0:3389           0.0.0.0:0              LISTENING       996
  TCP    0.0.0.0:10002          0.0.0.0:0              LISTENING       624
  TCP    0.0.0.0:10005          0.0.0.0:0              LISTENING       624
  TCP    0.0.0.0:10006          0.0.0.0:0              LISTENING       624
  TCP    0.0.0.0:11039          0.0.0.0:0              LISTENING       1900
  TCP    127.0.0.1:1067         0.0.0.0:0              LISTENING       2392
  TCP    127.0.0.1:4403         127.0.0.1:4404         ESTABLISHED     2464
  TCP    127.0.0.1:4404         127.0.0.1:4403         ESTABLISHED     2464
  TCP    127.0.0.1:4405         127.0.0.1:4406         ESTABLISHED     2464
  TCP    127.0.0.1:4406         127.0.0.1:4405         ESTABLISHED     2464

で、プロセスIDが分かったら、tasklistコマンドで実行ファイルとぶつけるです。これで分かれば、問題ないけど、svchost.exeとかだと、どのサービスか分からないですね。

C:\>tasklist

イメージ名                   PID セッション名     セッション# メモリ使用量
========================= ====== ================ ======== ============
System Idle Process            0 Console                 0         16 K
System                         4 Console                 0        236 K
smss.exe                     688 Console                 0        388 K
csrss.exe                    736 Console                 0     14,296 K
winlogon.exe                 760 Console                 0      3,876 K
services.exe                 804 Console                 0      5,632 K
lsass.exe                    816 Console                 0     35,456 K
svchost.exe                  996 Console                 0     37,860 K
svchost.exe                 1064 Console                 0     34,064 K
svchost.exe                 1152 Console                 0     75,356 K
svchost.exe                 1272 Console                 0     26,200 K

そこで、/svcオプションの登場。これを使えば、svchost.exeでも中身が分かるってことです。

C:\>tasklist /svc

イメージ名                   PID サービス
========================= ====== =============================================
System Idle Process            0 N/A
System                         4 N/A
smss.exe                     688 N/A
csrss.exe                    736 N/A
winlogon.exe                 760 N/A
services.exe                 804 Eventlog, PlugPlay
lsass.exe                    816 Netlogon, PolicyAgent, ProtectedStorage,
                                 SamSs
svchost.exe                  996 DcomLaunch, TermService
svchost.exe                 1064 RpcSs
svchost.exe                 1152 AudioSrv, Browser, CryptSvc, Dhcp, dmserver,
                                 ERSvc, EventSystem, helpsvc, HidServ,
                                 lanmanserver, lanmanworkstation, Netman,
                                 Nla, RasMan, Schedule, seclogon, SENS,
                                 SharedAccess, ShellHWDetection, srservice,
                                 TapiSrv, Themes, W32Time, winmgmt, wuauserv,
                                 WZCSVC
svchost.exe                 1272 Dnscache
svchost.exe                 1308 LmHosts, RemoteRegistry, SSDPSRV, WebClient

この手順はWindows XPWindows Server 2003で使えるらしいので、私はこれだけで十分そうです。似たようなことをやるために、WindowsではfportやActivePortsってソフトウェアがあるらしいです。ちなみにUnixの場合はlsofって外部コマンドが使えるらしいです。入れてないから試せませんでしたが。。。

なお、今回の手順はこちらの情報に基づいてます。というか、そのままです。

http://www.atmarkit.co.jp/fwin2k/win2ktips/236portcheck/portcheck.html

Java並行処理プログラミング読了

JavaEE 勉強会のお題になっていたので読み始めたこの本ですが、とっても面白かったです。マルチスレッドとか、簡単なことしかやったことありませんでしたが、この本を読むと何かマルチスレッドを無駄に使いたくなります。

Java5で並行処理の為のライブラリがこんなに充実していたことも今更ながらに勉強になったので、読んで良かったです。勉強会自体に全然参加できなかったのは心残りでしたが。。。

せっかくなので、あとがきにあったお題をやってみました。こんな感じかなぁ?

import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * @author jundu
 * 
 */
public class ThreadTest2 implements Runnable {

    private static final String[] jn = { "0", "1", "2", "3", "4", "5", "6",
            "7", "8", "9" };

    private int id;

    private String ids;

    private CountDownLatch latch;

    public ThreadTest2(int tid, CountDownLatch latch) {
        id = tid;
        ids = id < 10 ? jn[id] : String.valueOf(id);
        this.latch = latch;
    }

    /*
     * (non-Javadoc)
     * 
     * @see java.lang.Runnable#run()
     */
    public void run() {
        System.out.println(ids + "番のスレッドをスタートします");
        long stime = System.currentTimeMillis();
        for (int i = 0; i < 20000; ++i) {
            for (int j = 0; j < 20000; ++j) {
                double p = i * j;
                p = Math.sqrt(p);
            }
        }
        stime = System.currentTimeMillis() - stime;
        System.out.println(ids + "番のスレッドは" + stime + "ミリ秒かかりました");
        latch.countDown();
    }

    /**
     * @param args
     * @throws InterruptedException
     */
    public static void main(String[] args) throws InterruptedException {
        if (args.length < 1) {
            System.out.println("使い方: java ThreadTest2 x");
            System.out.println("xでスレッド数を指定してください。");
            System.exit(1);
        }

        int cpu = Integer.parseInt(args[0]);

        ExecutorService exec = Executors.newFixedThreadPool(cpu);
        CountDownLatch latch = new CountDownLatch(cpu);
        for (int i = 0; i < cpu; ++i) {
            exec.execute(new ThreadTest2(i, latch));
        }
        latch.await();
        exec.shutdown();
    }

}

コンポーネントの自動登録

DWRSeasar2対応をするに当たって、dwr.xmlを書かなくても良い仕組みを考えています。AutoRegisterと同じようにdiconファイルを記述することで、コンポーネントを自動的にDWRから呼び出せるようにするわけです。例えば、こんな感じですね。

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE components PUBLIC "-//SEASAR//DTD S2Container 2.3//EN"
          "http://www.seasar.org/dtd/components23.dtd">
<components>
    <include path="aop.dicon"/>
    <include path="s2dwr.dicon"/>
    <component class="org.seasar.dwr.example.remote.echo.EchoService">
        <aspect pointcut=".*">aop.traceInterceptor</aspect>
    </component>
    <component class="org.seasar.dwr.example.remote.calc.CalculatorService">
        <aspect pointcut=".*">aop.traceInterceptor</aspect>
    </component>
    <!-- dwr.xmlを書く代わり -->
    <component class="org.seasar.dwr.autoregister.DwrAutoRegister">
        <initMethod name="addClassPattern">
            <arg>"org.seasar.dwr.example.remote"</arg>
            <arg>".*Service"</arg>
        </initMethod>
    </component>
</components>

果たしてニーズがあるのか分かりませんが、私は設定ファイルを書くのが面倒に感じられたので、こんな仕組みを用意しようと思っています。

# これくらいしかS2的なことをやるところがないという話もありますが(^^;

S2DWRをちょっとずつ進めてみる

とりあえず冬休みになったので、DWRと戯れています。まずは、竹添さんのコードを参考にS2Creatorを作りつつ、気になっていたDWRから呼び出すコンポーネントアスペクトをかけるとListやMapなどのジェネリクス対応がうまくいかなくなる問題の調査です。

最初にDWRの調査。Java1.4の場合ジェネリクスがなかったのでListやMapの中に入れるべきインスタンスが特定できません。そのためにdwr.xmlという設定にJava5に似た構文で型の情報を定義できるようになっています。Java5の場合は、ジェネリクスを使っていれば、そこから情報を取ってくれるようです。

ところが、S2AOPを使った場合にこの処理がうまく動かなくなります。Java1.4の場合は、設定に書かれたクラス・メソッドと型を関連づけて保持しているので、S2AOPがエンハンスしたクラスの場合、元のクラスと異なるため設定が見つけられなくなります。

また、Java5の場合はエンハンスした結果できたサブクラスにジェネリクスの情報が引き継がれていないため、Java1.4と同じ状況になってしまいます。

この問題に対応するため、以下の日記では型情報を探しにいく時に、対象がエンハンスした結果できたサブクラス(クラス名に$$EnhancedByS2AOP$$を含む)の場合にスーパークラスを探して、そっちを処理されています。

http://d.hatena.ne.jp/masapon1967/20060831/1157086213

これを参考にやろうとしたのですが、DWR1.xと2.xでコードが変わっていて、同じ方法は使えませんでした。仕方なく、インバウンド処理の中でやることにしました。具体的には、インバウンド時に呼び出されるHtmlCallMarshallerとPlainCallMarshallerをそれぞれサブクラス化し、その中で型情報を取得する時にスーパークラスを参照することを考えています。

ただ、この実装が果たしてよいのかどうか、まだちょっと迷いがあります。今のところ、このタイミングでいい気はしているのですが、本当に他にないのかどうか。。。 もうちょっと他のコードを書きつつ悶々としてみます。

そろそろ、今年を反省してみる。

大分、年末が近づいてきました。今年は、新しい言語にも挑戦するということでJavaScriptを時間を見て他人のソースを読んだりして勉強していたのですが、思いの外時間が取れず、未だにサイ本すら読み終わらない始末。。。

とはいえ、Javaなどとは違う世界をかいま見ることができ、色々と刺激を受けました。そんなわけで、JavaScriptについては来年も継続課題として、もうちょっと読み書きできるようになりたいと思います。せめてJavaScriptビギナーから初級者くらいにはならないと。

JavaScriptだけでは面白くないので、サーバとの連携も試していきたいですね。お仕事などでも、やっぱりAjaxとか気になるわけですが、特定の人だけが実装できるっていう状態では、やりにくいですし。

ということで注目しているのはDWRです。Seasar2にはTeedaAjaxがあるのですが、Seasar2.3では動かないので。大人の事情という奴で、Seasar2.3で動かないとまずいのです。普通はそんなことないでしょうけど。

そんなわけで(?)、S2DWRとかSandboxあたりで作ったら、ニーズってあるのでしょうかね? やるとしても、まだまだこれから勉強して作っていくのでのんびりしたペースでしょうけど、来年はそういうところにも進出していきたいかなぁと思ってます。

もちろん、Seasar2Javadoc書いたり、S2Daoの改訂をしていくのだって忘れちゃいけません。忙しい時ほど、時間を作って仕事以外のことにもチャレンジをしていきたい、そんな感じで来年もよろしくお願いします。

というあいさつには、まだ早いですね(^^;

Seasar Conference 2007 Autumnのタイムテーブル発表&申し込み開始

Seasar Conference 2007 Autumnのタイムテーブルが出ました。なんか、盛りだくさんな感じです。入門者向けのひがさんのセッションと、それ以外の”好きな人は好き”って感じのテーマがバランスよく配置されている感じで、比較的みたいセッションを選びやすいと感じました。

そんなわけで私が今のところ見たいなぁとお持っているのは、こんな感じ。

  • 千葉先生ゲスト講演
  • S2JFaceによる、簡単リッチアプリケーション開発
  • テストは人のためならず
  • データベースプログラミングの生産性を10倍向上させるSeasar2の新機能
  • Adobeスポンサーセッション

他にも見たいセッションがいっぱいあるのですが、自分の興味がある領域と時間のかぶり方からこんな感じです。まぁ、当日までどれをみるのかは分かりませんが(^^;

とにもかくにも、大盛況だといいですね。