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

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

我在 中找到了很好的信息 Windows 搜索 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 位于您的类路径中,并且 jamin.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();
        }
    }
}

其他提示

由于这里几个帖子建议你可以使用像雅各布JNBridge的,J-的Integra等商用或免费的框架,Java和.NET或COM之间的桥梁.. 其实我有与这些第三方的一个(一个昂贵:-))的经验,我必须说,我会尽我所能,以避免重复这个错误的未来。其原因是,它涉及到许多“巫术”的东西,你真的不能调试,这是非常复杂的,了解是什么问题,当事情出错。

我建议你要实现的解决方案是创建一个简单的.NET应用程序,对Windows搜索API的实际调用。这样做之后,你需要建立这个组件和Java代码之间的通信通道。这可以通过各种方式通过信息发送到一个小数据库,你的应用程序将定期拉来完成,例如。或登记在机器IIS这个组件(如果存在)和暴露简单WS API与它通信。

我知道它听起来很麻烦,但明显的优点是:a)使用你它理解的语言(.NET或COM与窗口搜索API进行通信),B)可以控制所有应用程序的路径

任何原因,你不能只使用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();
    }
}

有几个库在那里为从Java调用COM对象,有些是开源(但它们的学习曲线是更高)有些是封闭的源并具有更快的学习曲线。一个封闭的源例如是 EZCom 。商业的人往往把重点放在呼吁从Windows的Java为好,这是我从来没有在开源见过。

在你的情况,我会建议你做的是前在自己的.NET类的调用(我想用C#作为最接近的Java并不进入有争议的J#),并专注于制作与互操作性.NET的DLL。这样的windows编程变得更容易,而Windows和Java之间的界面更简单。

如果你正在寻找如何使用Java COM库,在MSDN是放错了地方。但MSDN将帮助你写你从内.NET需要什么,再看看有关从.NET对象调用你需要的一种或两种方法COM库教程。

编辑:

鉴于有关使用Web服务,您可以(而且很可能会有更好的运气)建立一个小的.net应用程序调用一个嵌入式Java Web服务器上,而不是试图使.NET具有嵌入式Web服务的答案的讨论,并有Java的是呼叫的消费者。对于一个嵌入式Web服务器,我的研究表明温斯顿好。不是最小的,但更灵活。

要得到那个工作的方式是启动从Java的.NET应用程序,并拥有.NET应用程序调用一个计时器或循环中的Web服务,以查看是否有一个请求,如果有,过程它和发送响应。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top