从Java查询Windows搜索

Osc*_*Ryz 6 java windows-search

我想直接(或间接)从Java查询Windows Vista Search服务.

我知道可以使用search-ms:protocol进行查询,但我想在应用程序中使用结果.

我在Windows Search API中找到了很好的信息, 但没有一个与Java相关.

我认为接受了答案,提供了有关如何实现这一目标的有用和明确的信息.

提前致谢.

编辑

在我将此标记为已接受之前,是否有人有JACOB样本?:)

Jac*_*eow 20

您可能希望了解一种Java-COM集成技术.我亲自与JACOB(JAva COm Bridge)合作:

这是相当麻烦的(想想专门用反射工作),但为我完成了工作(快速证明概念,从Java中访问MapPoint).

我所知道的唯一其他此类技术是Jawin,但我没有任何个人经验:

2009年4月26日更新: 为了解决这个问题,我对Microsoft Windows Search做了更多研究,并找到了一种使用OLE DB与它集成的简单方法.这是我写的一些代码作为概念证明:

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();
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

要编译它,你需要确保JAWIN JAR在你的类路径中,并且jawin.dll在你的路径中(或java.library.path系统属性).此代码只是打开与本地Windows桌面搜索索引的ADO连接,使用关键字"Foo"查询文档,并在结果文档上打印出一些关键属性.

如果您有任何问题,请告诉我,或者需要我澄清一切.

2009年4月27日更新: 我也尝试在JACOB中实现相同的功能,并将做一些基准来比较两者之间的性能差异.我可能在JACOB中做错了什么,但它似乎一直在使用10倍以上的内存.如果我有时间的话,我也会研究jcom和com4j的实现,并试图找出一些我认为是由于某些地方缺乏线程安全性的怪癖.我甚至可以尝试基于JNI的解决方案.我希望在6-8周内完成所有工作.

更新04/28/2009: 这只是那些一直关注和好奇的人的更新.事实证明没有线程问题,我只需要显式关闭我的数据库资源,因为OLE DB连接可能是在操作系统级别汇集的(我可能应该关闭连接......).我认为我不会对此有任何进一步的更新.如果有人遇到任何问题,请告诉我.

更新05/01/2009: 根据奥斯卡的要求添加了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();
        }
    }
}
Run Code Online (Sandbox Code Playgroud)