Question

Je voudrais arriver à interroger Windows Vista service de recherche directement (ou indirectement) de Java.

Je sais qu'il est possible d'interroger en utilisant la recherche-ms: protocole, mais je voudrais consommer le résultat dans l'application

.

J'ai trouvé une bonne information dans le Windows Search API mais aucun lié à Java.

Je marquer comme accepté la réponse qui fournit des informations utiles et définitif sur la façon d'y parvenir.

Merci d'avance.

EDIT

Quelqu'un at-il un échantillon JACOB, avant que je puisse marquer cela comme accepté? :)

Était-ce utile?

La solution

Vous pouvez regarder une des technologies d'intégration Java-COM. J'ai personnellement travaillé avec JACOB (Pont COm Java):

Ce qui était assez lourd (pensez à travailler exclusivement avec la réflexion), mais a fait le travail pour moi (preuve rapide du concept, l'accès à MapPoint à partir de Java).

La seule autre cette technologie, je suis au courant est Jawin, mais je n'ai aucune expérience personnelle avec elle:

Mise à jour 26/04/2009: Juste pour le plaisir de le faire, je l'ai fait plus de recherche dans la recherche de Microsoft Windows, et a trouvé un moyen facile d'intégrer à l'aide de OLE DB. Voici un code que j'ai écrit comme une preuve de concept:

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();
        }
    }
}

Pour compiler cela, vous devez vous assurer que le JAR JAWIN est dans votre classpath, et que jawin.dll est dans votre chemin (ou propriété système java.library.path). Ce code ouvre simplement une connexion ADO à l'index local Windows Desktop Search, les requêtes pour les documents avec le mot-clé « Foo » et imprimer quelques propriétés clés sur les documents qui en résultent.

Laissez-moi savoir si vous avez des questions ou besoin de moi pour quoi que ce soit préciser.

Mise à jour 04/27/2009: J'ai essayé de mettre en œuvre la même chose dans JACOB aussi bien, et allez faire quelques points de repère pour comparer les différences de performance entre les deux. Je peux faire quelque chose de mal dans JACOB, mais il semble être toujours en utilisant 10 fois plus de mémoire. Je vais travailler sur une mise en œuvre de JCOM et com4j ainsi, si j'ai un certain temps, et essayer de comprendre quelques bizarreries que je crois en raison du manque quelque part de la sécurité des threads. Je peux même essayer une solution JNI. Je pense à faire avec tout en 6-8 semaines.

Mise à jour 04/28/2009: Ceci est juste une mise à jour pour ceux qui ont été à la suite et curieux. Il s'avère qu'il n'y a pas de problèmes de filetage, je avais juste besoin de fermer explicitement mes ressources de base de données, car les connexions OLE DB sont probablement mis en commun au niveau de l'OS (je devrais probablement avoir fermé les connexions quand même ...). Je ne pense pas que je serai d'autres mises à jour de cela. Faites-moi savoir si quelqu'un se heurte à aucun problème avec cela.

Mise à jour 05/01/2009: Ajout d'un exemple JACOB par la demande d'Oscar. Cela passe par la même séquence exacte des appels à partir d'un point de vue COM, juste en utilisant JACOB. Il est vrai JACOB a été beaucoup plus travaillé activement dans ces derniers temps, je remarque aussi qu'il est tout à fait un porc de mémoire (utilise 10 fois plus de mémoire que la version 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();
        }
    }
}

Autres conseils

Comme quelques messages suggèrent ici que vous pouvez pont entre Java et .NET ou COM à l'aide des cadres commerciaux ou libres comme JACOB, JNBridge, J-Integra etc .. En fait, j'ai eu une expérience avec l'une de ces tiers (un cher un :-)) et je dois dire que je ferai de mon mieux pour éviter de répéter cette erreur à l'avenir. La raison en est qu'il implique des choses beaucoup « voodoo » vous ne pouvez pas vraiment debug, il est très compliqué de comprendre ce qui est le problème quand les choses vont mal.

La solution que je vous suggère de mettre en œuvre est de créer une simple application .NET qui rend les appels réels aux fenêtres API de recherche. Après cela, vous devez établir un canal de communication entre ce composant et votre code Java. Cela peut se faire de différentes manières, par exemple par messagerie à une petite base de données que votre application périodiquement tirer. Ou l'enregistrement de ce composant sur la machine IIS (si elle existe) et d'exposer API simple WS pour communiquer avec lui.

Je sais que cela peut sembler lourd, mais les avantages évidents sont: a) vous communiquer avec Windows API de recherche en utilisant la langue qu'il comprend (.NET ou COM), b) que vous contrôlez tous les chemins d'application

.

Toute raison pour laquelle vous ne pouviez pas simplement utiliser Runtime.exec() pour interroger via search-ms et lire le BufferedReader avec le résultat de la commande? Par exemple:

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();
    }
}

Il existe plusieurs bibliothèques là-bas pour appeler des objets COM de Java, certains sont opensource (mais leur courbe d'apprentissage est plus élevé) certains sont la source fermée et une courbe d'apprentissage plus rapide. Un exemple de source fermé est EZCom . Les commerciaux ont tendance à se concentrer sur l'appel java des fenêtres aussi bien, quelque chose que je ne l'ai jamais vu dans opensource.

Dans votre cas, ce que je vous suggère de faire est avant l'appel dans votre propre classe .NET (je suppose que l'utilisation C # comme c'est le plus proche de Java sans entrer dans la controverse J #), et de se concentrer à rendre l'interopérabilité avec les dll .NET. De cette façon, la programmation Windows devient plus facile, et l'interface entre Windows et java est plus simple.

Si vous cherchez comment utiliser une bibliothèque com java, le MSDN est au mauvais endroit. Mais le MSDN vous aidera à écrire ce que vous avez besoin à partir de .NET, puis regarder les tutoriels bibliothèque com sur les invoquer une ou deux méthodes dont vous avez besoin de vos objets .NET.

EDIT:

Compte tenu de la discussion dans les réponses sur l'utilisation d'un service Web, vous pouvez (et probablement aurez plus de chance) construire une petite application .NET qui appelle un serveur web java embarqué plutôt que d'essayer de faire .NET ont le service Web intégré et que java soit le consommateur de l'appel. Pour un serveur Web intégré, ma recherche a montré Winstone pour être bon. Pas le plus petit, mais il est beaucoup plus souple.

La manière d'obtenir que le travail est de lancer l'application .NET de Java, et avoir l'application .NET appelez le service Web sur une minuterie ou une boucle pour voir s'il y a une demande, et s'il y a, processus et envoyer la réponse.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top