java - 从 Java 查询 Windows 搜索

标签 java windows-search

我想直接(或间接)从 Java 查询 Windows Vista 搜索服务。

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

我在 Windows Search API 中找到了很好的信息但与 Java 无关。

我会将提供有关如何实现此目标的有用且明确信息的答案标记为已接受。

提前致谢。

编辑

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

最佳答案

您可能想了解其中一种 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();
        }
    }
}

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

如果您有任何问题或需要我澄清任何问题,请告诉我。

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

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

2009 年 5 月 1 日更新: 根据 Oscar 的要求添加了 JACOB 示例。从 COM 的角度来看,这将经历完全相同的调用序列,只是使用 JACOB。虽然最近 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();
        }
    }
}

关于java - 从 Java 查询 Windows 搜索,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/779793/

相关文章:

java - 使用 Java 将文件上传和 POST 到 PHP 页面

c# - 指定机器名时无法在自己的机器上查询SystemIndex

algorithm - 自动获取术语列表,导入 Windows 搜索功能(针对内容),并导出结果列表。 (自动?)

c# - KB4022726 破坏 OleDb 上的 Windows 搜索查询

windows-search - 如何启动/停止/暂停 Windows 搜索索引器

java - 如何通过鼠标单击按钮来更改小程序的大小(宽度x高度)?

java - 如何更改tomcat上的log4j2日志记录路径?

c# - 我可以手动注册/安装 Search.Collat​​orDSO.1

java - csv 解析器读取 header

java - 使用POST方法发送数据,android studio单例