Domanda

Mi piacerebbe arrivare a interrogare servizio di ricerca di Windows Vista direttamente (o indirettamente) da Java.

So che è possibile interrogare utilizzando la ricerca-MS: protocollo, ma vorrei consumare il risultato all'interno della app

.

Ho trovato una buona informazione nel di Windows Search API ma nessuno relativi a Java.

Vorrei segnare come accettato la risposta che fornisce informazioni utili e definitivo su come raggiungere questo obiettivo.

Grazie in anticipo.

Modifica

Qualcuno ha un campione JACOB, prima di poter celebrare questo accettata? :)

È stato utile?

Soluzione

Si consiglia di guardare in una delle tecnologie di integrazione Java-COM. Personalmente ho lavorato con JACOB (COM Java Bridge):

che era piuttosto ingombrante (si pensi che lavora esclusivamente con riflessione), ma ha ottenuto il lavoro fatto per me (Quick Proof of concept, accesso MapPoint all'interno di Java).

L'unico altro tale tecnologia io sappia è Jawin, ma non ho alcuna esperienza personale con esso:

Aggiornamento 2009/04/26: Solo per il gusto di farlo, ho fatto più ricerca in Microsoft Windows Search, e ha trovato un modo semplice per integrarsi con essa utilizzando OLE DB. Ecco alcuni codice che ho scritto come prova di concetto:

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

Per compilare questo, è necessario assicurarsi che il JAR JAWIN è nel vostro percorso di classe, e che jawin.dll è nel vostro (o proprietà di sistema java.library.path) percorso. Questo codice apre semplicemente una connessione ADO al desktop di Windows Indice di ricerca locale, le query per i documenti con la parola chiave "Pippo", e stampare alcune proprietà fondamentali sui documenti risultanti.

Fatemi sapere se avete domande o mi bisogno di chiarire nulla.

Aggiornamento 2009/04/27: Ho provato a implementare la stessa cosa in JACOB pure, e faranno alcuni benchmark per confrontare le differenze di prestazioni tra i due. Posso essere facendo qualcosa di sbagliato in Giacobbe, ma sembra essere coerente con 10x più memoria. Lavorerò su un'implementazione jcom e com4j così, se ho un po 'di tempo, e cercare di capire alcune stranezze che ritengo a causa della mancanza di sicurezza dei thread da qualche parte. Potrei anche provare una soluzione basata JNI. Mi aspetto di essere fatto con tutto in 6-8 settimane.

Aggiornamento 2009/04/28: Questo è solo un aggiornamento per coloro che avete seguito e curioso. Risulta non ci sono problemi di threading, ho solo bisogno di chiudere esplicitamente le mie risorse di database, dal momento che le connessioni OLE DB sono presumibilmente messe in comune a livello di sistema operativo (probabilmente avrei dovuto chiudere i collegamenti in ogni caso ...). Non credo che sarò ulteriori aggiornamenti su questo. Fatemi sapere se qualcuno si imbatte in problemi con questo.

Aggiornamento 05/01/2009: Aggiunto JACOB esempio per richiesta di Oscar. Questo passa attraverso la stessa sequenza di chiamate da un punto di vista COM, solo con Jacob. Mentre è vero JACOB è stato molto più attivamente lavorato in questi ultimi tempi, ho anche notato che è piuttosto ingordo di memoria (usa 10 volte la quantità di memoria della versione 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();
        }
    }
}

Altri suggerimenti

Come qualche post qui suggeriscono è possibile colmare tra Java e .NET o COM utilizzando gli schemi commerciali o gratuiti come JACOB, JNBridge, J-Integra, ecc .. In realtà ho avuto un'esperienza con con una di queste terze parti (un costoso uno :-)) e devo dire che farò del mio meglio per evitare di ripetere questo errore in futuro. La ragione è che si tratta di molte cose "voodoo" non si può davvero eseguire il debug, è molto complicato da capire qual è il problema quando le cose vanno male.

La soluzione vorrei suggerire di implementare è quello di creare una semplice applicazione .NET che rende le chiamate effettivi alle API di ricerca di Windows. Dopo questo modo, è necessario stabilire un canale di comunicazione tra questo componente e il codice Java. Questo può essere fatto in diversi modi, ad esempio messaggistica ad un piccolo DB che l'applicazione periodicamente tirare. O la registrazione di questa componente sul IIS macchina (se esiste) ed esporre semplice API WS per comunicare con esso.

Lo so che può sembrare ingombrante ma i vantaggi evidenti sono: a) di comunicare con Windows Search API utilizzando il linguaggio capisce (NET o COM), b) è possibile controllare tutti i percorsi di applicazione

.

Qual è il motivo per cui non si potrebbe utilizzare Runtime.exec() per interrogare tramite search-ms e leggere il BufferedReader con il risultato del comando? Ad esempio:

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

Ci sono diverse librerie là fuori per chiamare oggetti COM da Java, alcuni sono opensource (ma la loro curva di apprendimento è più alto) alcuni sono closed source e hanno una curva di apprendimento più veloce. Un esempio sorgente chiuso sia EZcom . Quelli commerciali tendono a concentrarsi sulla chiamata java dalle finestre pure, qualcosa che non ho mai visto in opensource.

Nel tuo caso, quello che vorrei suggerire che fate è davanti la chiamata nella propria classe .NET (immagino uso C # come che è più vicino a Java, senza entrare nel controverso J #), e concentrarsi sul rendere l'interoperabilità con la dll .NET. In questo modo la programmazione di Windows diventa più facile, e l'interfaccia tra Windows e Java è più semplice.

Se siete alla ricerca di come utilizzare una libreria COM Java, la MSDN è il posto sbagliato. Ma il MSDN vi aiuterà a scrivere quello che ti serve da dentro NET, e poi guardare il tutorial libreria COM circa invocando uno o due metodi avete bisogno dal vostro oggetti .NET.

EDIT:

Data la discussione nelle risposte sull'utilizzo di un servizio Web, si potrebbe (e probabilmente avrà più fortuna) costruire una piccola applicazione .NET che chiama un server Web Java incorporato, piuttosto che cercare di rendere .NET avere il servizio Web incorporato , e hanno java sia il consumatore della chiamata. Per un server Web incorporato, la mia ricerca ha dimostrato Winstone di essere buono. Non la più piccola, ma è molto più flessibile.

Il modo per ottenere che il lavoro è quello di lanciare l'applicazione .NET da Java, e avere l'applicazione .NET chiamare il servizio Web su un timer o un ciclo per vedere se c'è una richiesta, e se c'è, processo e inviare la risposta.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top