6

Java から直接 (または間接的に) Windows Vista Search サービスにクエリを実行したいと考えています。

search-ms: プロトコルを使用してクエリを実行できることはわかっていますが、アプリ内で結果を使用したいと考えています。

Windows Search APIで良い情報を見つけました が、Java に関連する情報はありませんでした。

これを達成する方法に関する有用で決定的な情報を提供する回答を承認済みとしてマークします。

前もって感謝します。

編集

これを承認済みとしてマークする前に、JACOB サンプルを持っている人はいますか? :)

4

4 に答える 4

20

Java-COM 統合テクノロジの 1 つを参照することをお勧めします。私は個人的に JACOB (JAva COM Bridge) と協力してきました:

これはかなり面倒でしたが (リフレクションのみで作業することを考えてください)、仕事は完了しました (概念の迅速な証明、Java 内から MapPoint へのアクセス)。

私が知っている他のそのようなテクノロジーは Jawin だけですが、個人的な経験はありません。

更新 2009 年 4 月 26 日: 念のため、Microsoft Windows Search についてさらに調査したところ、OLE DB を使用して Microsoft Windows Search と簡単に統合する方法を見つけました。概念実証として私が書いたコードを次に示します。

public static void main(String[] args) {
    DispatchPtr connection = null;
    DispatchPtr results = null;
    try {
        Ole32.CoInitialize();
        connection = new DispatchPtr("ADODB.Connection");
        connection.invoke("Open",
            "Provider=Search.CollatorDSO;" +
            "Extended Properties='Application=Windows';");
        results = (DispatchPtr)connection.invoke("Execute",
            "select System.Title, System.Comment, System.ItemName, System.ItemUrl, System.FileExtension, System.ItemDate, System.MimeType " +
            "from SystemIndex " +
            "where contains('Foo')");
        int count = 0;
        while(!((Boolean)results.get("EOF")).booleanValue()) {
            ++ count;
            DispatchPtr fields = (DispatchPtr)results.get("Fields");
            int numFields = ((Integer)fields.get("Count")).intValue();

            for (int i = 0; i < numFields; ++ i) {
                DispatchPtr item =
                    (DispatchPtr)fields.get("Item", new Integer(i));
                System.out.println(
                    item.get("Name") + ": " + item.get("Value"));
            }
            System.out.println();
            results.invoke("MoveNext");
        }
        System.out.println("\nCount:" + count);
    } catch (COMException e) {
        e.printStackTrace();
    } finally {
        try {
            results.invoke("Close");
        } catch (COMException e) {
            e.printStackTrace();
        }
        try {
            connection.invoke("Close");
        } catch (COMException e) {
            e.printStackTrace();
        }
        try {
            Ole32.CoUninitialize();
        } catch (COMException e) {
            e.printStackTrace();
        }
    }
}

これをコンパイルするには、JAWIN JAR がクラスパスにあり、jawin.dll がパス (または java.library.path システム プロパティ) にあることを確認する必要があります。このコードは、単純にローカルの Windows デスクトップ サーチ インデックスへの ADO 接続を開き、キーワード「Foo」でドキュメントをクエリし、結果のドキュメントにいくつかの重要なプロパティを出力します。

ご不明な点がございましたら、お気軽にお問い合わせください。

2009 年 4 月 27 日更新: 同じことを JACOB にも実装してみました。2 つのパフォーマンスの違いを比較するために、いくつかのベンチマークを行う予定です。JACOB で何か間違ったことをしている可能性がありますが、一貫して 10 倍のメモリを使用しているようです。時間があれば、jcom と com4j の実装にも取り組み、どこかでスレッド セーフが欠如していると思われるいくつかの癖を見つけようとします。JNI ベースのソリューションを試すこともできます。6〜8週間ですべてが完了すると思います。

更新 2009 年 4 月 28 日: これは、フォローしていて興味を持っている人のための単なる更新です。OLE DB接続はおそらくOSレベルでプールされているため、スレッドの問題はありません。データベースリソースを明示的に閉じる必要がありました(とにかく接続を閉じる必要がありました...)。これ以上の更新はないと思います。これで問題が発生した場合はお知らせください。

2009 年 5 月 1日更新: Oscar の要求により、JACOB の例を追加しました。これは、JACOB を使用するだけで、COM の観点からはまったく同じ一連の呼び出しを実行します。確かに、JACOB は最近より積極的に取り組んでいますが、メモリを大量に消費していることにも気付きました (Jawin バージョンの 10 倍のメモリを使用します)。

public static void main(String[] args) {
    Dispatch connection = null;
    Dispatch results = null;

    try {
        connection = new Dispatch("ADODB.Connection");
        Dispatch.call(connection, "Open",
            "Provider=Search.CollatorDSO;Extended Properties='Application=Windows';");
        results = Dispatch.call(connection, "Execute",
            "select System.Title, System.Comment, System.ItemName, System.ItemUrl, System.FileExtension, System.ItemDate, System.MimeType " +
            "from SystemIndex " +
            "where contains('Foo')").toDispatch();
        int count = 0;
        while(!Dispatch.get(results, "EOF").getBoolean()) {
            ++ count;
            Dispatch fields = Dispatch.get(results, "Fields").toDispatch();
            int numFields = Dispatch.get(fields, "Count").getInt();

            for (int i = 0; i < numFields; ++ i) {
                Dispatch item =
                    Dispatch.call(fields, "Item", new Integer(i)).
                    toDispatch();
                System.out.println(
                    Dispatch.get(item, "Name") + ": " +
                    Dispatch.get(item, "Value"));
            }
            System.out.println();
            Dispatch.call(results, "MoveNext");
        }
    } finally {
        try {
            Dispatch.call(results, "Close");
        } catch (JacobException e) {
            e.printStackTrace();
        }
        try {
            Dispatch.call(connection, "Close");
        } catch (JacobException e) {
            e.printStackTrace();
        }
    }
}
于 2009-04-25T00:42:36.927 に答える
3

ここでのいくつかの投稿は、JACOB、JNBridge、J-Integra などの商用または無料のフレームワークを使用して、Java と .NET または COM の間をブリッジできることを示唆しています。 )そして、将来この過ちを繰り返さないように最善を尽くすと言わなければなりません. その理由は、実際にはデバッグできない多くの「ブードゥー」なものが含まれているためです。問題が発生したときに何が問題なのかを理解するのは非常に複雑です。

実装することをお勧めする解決策は、Windows Search API を実際に呼び出す単純な .NET アプリケーションを作成することです。その後、このコンポーネントと Java コードの間に通信チャネルを確立する必要があります。これは、アプリケーションが定期的にプルする小さな DB にメッセージを送るなど、さまざまな方法で実行できます。または、マシン IIS (存在する場合) にこのコンポーネントを登録し、単純な WS API を公開して、それと通信します。

面倒に聞こえるかもしれませんが、明らかな利点は次のとおりです。a) 理解できる言語 (.NET または COM) を使用して Windows Search API と通信する、b) すべてのアプリケーション パスを制御する。

于 2009-04-28T13:55:23.797 に答える
1

コマンドの結果を使用Runtime.exec()してクエリを実行しsearch-msて読み取ることができなかった理由は何ですか? BufferedReader例えば:

public class ExecTest {
    public static void main(String[] args) throws IOException {
        Process result = Runtime.getRuntime().exec("search-ms:query=microsoft&");

        BufferedReader output = new BufferedReader(new InputStreamReader(result.getInputStream()));
        StringBuffer outputSB = new StringBuffer(40000);
        String s = null;

        while ((s = output.readLine()) != null) {
            outputSB.append(s + "\n");
            System.out.println(s);
        }

        String result = output.toString();
    }
}
于 2009-04-25T00:29:36.253 に答える
0

Java から COM オブジェクトを呼び出すためのライブラリがいくつかあります。一部はオープンソース (ただし、学習曲線はより長くなります) であり、一部はクローズド ソースであり、学習曲線がより速くなります。クローズド ソースの例はEZComです。商用のものは、Windows からの Java の呼び出しにも重点を置く傾向があります。これは、オープンソースでは見たことがないものです。

あなたの場合、私があなたに提案することは、あなた自身の.NETクラスで呼び出しを行うことです(物議を醸すJ#に入ることなく、Javaに最も近いC#を使用すると思います)、.NET dllとの相互運用性を高めることに焦点を当てます. そうすれば、Windows プログラミングがより簡単になり、Windows と Java の間のインターフェースがより単純になります。

Java com ライブラリの使用方法を探している場合、MSDN は間違った場所です。ただし、MSDN は、.NET 内から必要なものを作成するのに役立ちます。次に、.NET オブジェクトから必要な 1 つまたは 2 つのメソッドを呼び出す方法について、com ライブラリのチュートリアルを参照してください。

編集:

Web サービスの使用に関する回答の議論を考えると、.NET に組み込みの Web サービスを持たせようとするのではなく、組み込みの Java Web サーバーを呼び出す小さな .NET アプリを構築することができます (おそらく運が良いでしょう)。 java が呼び出しのコンシューマになります。組み込み Web サーバーの場合、私の調査では、Winstoneが優れていることがわかりました。最小ではありませんが、はるかに柔軟です。

これを機能させる方法は、Java から .NET アプリを起動し、タイマーまたはループで .NET アプリに Web サービスを呼び出して、要求があるかどうかを確認し、ある場合はそれを処理して送信することです。応答。

于 2009-04-26T17:14:26.503 に答える