Вопрос

Я хотел бы получить возможность напрямую (или косвенно) запрашивать службу поиска Windows Vista из Java.

Я знаю, что можно выполнить запрос с помощью search-ms:протокол, но я хотел бы использовать результат в приложении.

Я нашел хорошую информацию в API поиска Windows но ничего не связанного с Java.

Я бы отметил как принятый ответ, содержащий полезную и точную информацию о том, как этого добиться.

Заранее спасибо.

РЕДАКТИРОВАТЬ

Есть ли у кого-нибудь образец JACOB, прежде чем я смогу отметить его как принятый?:)

Это было полезно?

Решение

Возможно, вы захотите взглянуть на одну из технологий интеграции Java-COM.Я лично работал с JACOB (JAva COM Bridge):

Это было довольно громоздко (думаю, что я работаю исключительно с отражением), но выполнило свою работу за меня (быстрая проверка концепции, доступ к MapPoint из Java).

Единственная известная мне подобная технология — это Jawin, но у меня нет личного опыта работы с ней:

Обновление от 26.04.2009:Просто ради интереса я провел дополнительное исследование 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).Этот код просто открывает соединение ADO с локальным индексом Windows Desktop Search, запрашивает документы с ключевым словом «Foo» и распечатывает несколько ключевых свойств результирующих документов.

Дайте мне знать, если у вас есть какие-либо вопросы или вам нужно, чтобы я что-то прояснил.

Обновление от 27.04.2009:Я попробовал реализовать то же самое в JACOB и собираюсь провести несколько тестов, чтобы сравнить разницу в производительности между ними.Возможно, я делаю что-то не так в JACOB, но кажется, что он постоянно использует в 10 раз больше памяти.Я также буду работать над реализацией jcom и com4j, если у меня будет немного времени, и попытаюсь выяснить некоторые особенности, которые, по моему мнению, связаны с отсутствием где-то потокобезопасности.Возможно, я даже попробую решение на основе JNI.Я рассчитываю закончить со всем за 6-8 недель.

Обновление от 28.04.2009:Это просто обновление для тех, кто следит и интересуется.Оказывается, проблем с потоками нет, мне просто нужно было явно закрыть ресурсы базы данных, поскольку соединения OLE DB предположительно объединяются на уровне ОС (вероятно, мне все равно следовало закрыть соединения...).Я не думаю, что у меня будут какие-либо дальнейшие обновления по этому поводу.Дайте мне знать, если у кого-нибудь возникнут какие-либо проблемы с этим.

Обновление от 01.05.2009:Добавлен пример JACOB по просьбе Оскара.С точки зрения COM это происходит через ту же самую последовательность вызовов, только с использованием JACOB.Хотя это правда, что в последнее время над JACOB работают гораздо активнее, я также заметил, что он сильно потребляет память (использует в 10 раз больше памяти, чем версия Jawin).

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 и .NET или COM, используя коммерческие или бесплатные платформы, такие как JACOB, JNBridge, J-Integra и т. д.На самом деле у меня был опыт общения с одной из этих третьих сторон (дорогой :-)), и я должен сказать, что сделаю все возможное, чтобы не повторять эту ошибку в будущем.Причина в том, что здесь задействовано множество «вудуистских» вещей, которые невозможно отладить. Очень сложно понять, в чем проблема, когда что-то идет не так.

Решение, которое я предлагаю вам реализовать, — это создать простое .NET-приложение, которое будет выполнять фактические вызовы API поиска Windows.После этого вам необходимо установить канал связи между этим компонентом и вашим Java-кодом.Это можно сделать разными способами, например, отправив сообщение в небольшую БД, которую ваше приложение будет периодически извлекать.Или зарегистрировать этот компонент на машине IIS (если он существует) и предоставить простой WS API для связи с ним.

Я знаю, что это может показаться громоздким, но очевидные преимущества:а) вы взаимодействуете с API поиска Windows, используя язык, который он понимает (.NET или COM), б) вы контролируете все пути приложения.

Любая причина, по которой вы не можете просто использовать 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();
    }
}

Существует несколько библиотек для вызова COM-объектов из Java, некоторые из них с открытым исходным кодом (но их кривая обучения выше), некоторые с закрытым исходным кодом и имеют более быструю кривую обучения.Пример с закрытым исходным кодом: ЭЗКом.Коммерческие, как правило, сосредоточены на вызове Java из Windows, чего я никогда не видел в opensource.

В вашем случае я бы посоветовал вам выполнить вызов в вашем собственном классе .NET (я думаю, используйте C#, поскольку он наиболее близок к Java, не вдаваясь в спорный J#) и сосредоточьтесь на обеспечении совместимости с .NET dll. .Таким образом, программирование для Windows становится проще, а интерфейс между Windows и Java упрощается.

Если вы ищете, как использовать библиотеку Java Com, MSDN — не то место.Но MSDN поможет вам написать то, что вам нужно, из .NET, а затем просмотреть руководства по библиотеке com, посвященные вызову одного или двух необходимых вам методов из ваших объектов .NET.

РЕДАКТИРОВАТЬ:

Учитывая обсуждение в ответах использования веб-службы, вы могли бы (и, вероятно, вам повезет больше) создать небольшое приложение .NET, которое вызывает встроенный веб-сервер Java, а не пытаться заставить .NET иметь встроенный веб-сервис и java быть потребителем вызова.Мои исследования показали, что для встроенного веб-сервера Уинстон быть хорошим.Не самый маленький, но гораздо более гибкий.

Чтобы заставить это работать, нужно запустить приложение .NET из Java и заставить приложение .NET вызывать веб-службу по таймеру или в цикле, чтобы проверить, есть ли запрос, и если есть, обработать его и отправить. ответ.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top