2009-04-23 12 views
6

Me gustaría hacer una consulta directamente al servicio de búsqueda de Windows Vista (o indirectamente) desde Java.Query Windows Search de Java

Sé que es posible consultar utilizando el protocolo search-ms: pero me gustaría consumir el resultado dentro de la aplicación.

He encontrado buena información en el Windows Search API pero ninguna relacionada con Java.

Marcaré como aceptada la respuesta que proporciona información útil y definitiva sobre cómo lograr esto.

Gracias de antemano.

EDITAR

¿Alguien tiene una muestra JACOB, antes de que pueda marcar esto como aceptado? :)

Respuesta

19

Es posible que desee ver una de las tecnologías de integración Java-COM. He trabajado personalmente con Jacob (Java Puente COM):

que era bastante engorroso (piensa trabajar exclusivamente con la reflexión), pero consiguió el trabajo hecho por mí (la prueba rápida del concepto, accediendo a MapPoint desde dentro de Java).

El único otro tipo de tecnología yo sepa es Jawin, pero no tengo ninguna experiencia personal con:

Actualización 26/04/2009: Simplemente por pura casualidad investigué más en Microsoft Windows Search y encontré una manera fácil de integrarlo utilizando OLE DB. Aquí hay algo de código que he escrito como una prueba de concepto:

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

Para compilar este, que necesita para asegurarse de que el JAR Jawin está en la ruta de clases, y que jawin.dll está en su camino (o java propiedad del sistema .library.path). Este código simplemente abre una conexión ADO al índice local de Windows Desktop Search, consulta documentos con la palabra clave "Foo" e imprime algunas propiedades clave en los documentos resultantes.

Avíseme si tiene alguna pregunta o si necesita que le aclare algo.

Actualización 04/27/2009: Probé la ejecución del mismo en JACOB, así, y voy a hacer algunos puntos de referencia para comparar las diferencias de rendimiento entre los dos. Puede que esté haciendo algo mal en JACOB, pero parece que consistentemente está usando 10 veces más memoria. Trabajaré en una implementación de jcom y com4j también, si tengo algo de tiempo, y trataré de descubrir algunas peculiaridades que creo que se deben a la falta de seguridad en el hilo en alguna parte. Incluso puedo probar una solución basada en JNI.Espero terminar con todo en 6-8 semanas.

Actualización 04/28/2009: Esto es solo una actualización para aquellos que han estado siguiendo y curiosos. Resulta que no hay problemas de enhebrado, solo necesitaba cerrar explícitamente los recursos de mi base de datos, ya que las conexiones OLE DB están supuestamente agrupadas en el nivel del sistema operativo (probablemente debería haber cerrado las conexiones de todos modos ...). No creo que haya más actualizaciones de esto. Avíseme si alguien tiene algún problema con esto.

Actualización 05/01/2009: Ejemplo de JACOB agregado por solicitud del Oscar. Esto pasa por la misma secuencia de llamadas desde una perspectiva COM, simplemente usando JACOB. Si bien es cierto JACOB se ha trabajado mucho más activa en los últimos tiempos, también me doy cuenta de que es todo un cerdo de la memoria (utiliza 10 veces más memoria que la versión 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(); 
     } 
    } 
} 
+0

Debería haber agregado No sé mucho de la programación de Windows: -S He visto esta biblioteca antes, pero nunca recibí mucha más aún porque no estoy seguro de qué hacer a continuación? ¿Puede hacer que la búsqueda de muestra en la documentación de MSDN funcione con jacob? – OscarRyz

+0

¡Esto fue muy interesante! Soy un novato que está estudiando informática y me pregunto dónde puedo obtener más información sobre ventanas "entrantes" y hacer cosas como esa desde Java o cualquier otro idioma. ¿Algún título para libros o páginas web? He usado días leyendo en msdn, pero no es para principiantes ... :) – Johannes

+0

No conozco ninguno, realmente solo he echado un vistazo rápido a la documentación de Jawin, y luego las referencias de la API del componente COM disponibles de Microsoft . Es un comienzo, pero sospecho que me encontraré con muchos más problemas si estuviera intentando algo más complejo. –

1

Cualquier razón por la cual no se podía utilizar sólo Runtime.exec() para consultar a través de search-ms y leer el BufferedReader con el resultado del comando? Por ejemplo:

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

Lea la segunda línea. Lo que he logrado hacer es invocar el Explorador de Windows para mostrar los resultados. No es exactamente lo que necesito (lea el final en la línea n. ° 2). O, ¿me estoy perdiendo algo aquí? – OscarRyz

+0

Ah, tienes razón. No estoy familiarizado con Windows Search y estoy corriendo en una Mac, así que no me di cuenta de que invocaría a Explorer. ¡Lo siento por eso! –

+0

No hay problema. Gracias de todos modos por la ayuda. Por cierto, para hacer que su publicación se ejecute debería ser como: http://pastebin.com/fa34637e – OscarRyz

0

Hay varias bibliotecas por ahí para llamar Los objetos COM de Java, algunos son de código abierto (pero su curva de aprendizaje es más alta) algunos son de código cerrado y tienen una curva de aprendizaje más rápida. Un ejemplo de fuente cerrada es EZCom. Los comerciales tienden a centrarse en llamar a Java desde Windows también, algo que nunca he visto en opensource.

En su caso, lo que le sugiero que haga es atender la llamada en su propia clase .NET (supongo que use C# como el más cercano a Java sin entrar en el controvertido J #), y centrarse en hacer la interoperabilidad con el .NET dll. De esa forma, la programación de Windows se vuelve más fácil, y la interfaz entre Windows y Java es más simple.

Si está buscando cómo usar una biblioteca de java com, MSDN es el lugar equivocado. Pero MSDN te ayudará a escribir lo que necesites desde .NET y luego verás los tutoriales de la biblioteca de com sobre cómo invocar uno o dos métodos que necesitas de tus objetos .NET.

EDIT:

Teniendo en cuenta lo expuesto en las respuestas sobre el uso de un servicio Web, usted podría (y probablemente tendrá mejor suerte) construir una pequeña aplicación .NET que llama a un servidor web Java embebido en lugar de tratar de hacer .NET tiene el servicio web incorporado, y java es el consumidor de la llamada. Para un servidor web incorporado, mi investigación mostró que Winstone es bueno. No es el más pequeño, pero es mucho más flexible.

La forma de hacerlo funcionar es iniciar la aplicación .NET desde Java, y hacer que la aplicación .NET llame al servicio web en un temporizador o un ciclo para ver si hay una solicitud, y si es así, procesarlo y enviar la respuesta.

+0

No busca exactamente una biblioteca java/com (al menos esa no es la razón de ser de la pregunta) pero consume la búsqueda de Windows desde Java. (Aunque las pocas respuestas que tengo van en dirección java/com lib) – OscarRyz

+0

La única manera de consumir una búsqueda de Windows es con una API de Windows, por lo que la única forma de interactuar con esa API de Windows es algo como COM , DCOM o CORBA o algún tipo de capa de socket (como servicios web). Es por eso que todos te estamos señalando a un puente java/com. – Yishai

3

Como pocas publicaciones aquí sugieren que puede tender un puente entre Java y .NET o COM utilizando marcos comerciales o gratuitos como JACOB, JNBridge, J-Integra, etc. En realidad tuve una experiencia con uno de estos terceros (un uno caro :-)) y debo decir que haré todo lo posible para evitar repetir este error en el futuro. La razón es que involucra muchas cosas "vudú" que realmente no se pueden depurar, es muy complicado entender cuál es el problema cuando las cosas van mal.

La solución que sugiero que implemente es crear una aplicación .NET simple que realice las llamadas reales a la API de búsqueda de Windows. Después de hacerlo, debe establecer un canal de comunicación entre este componente y su código Java. Esto se puede hacer de varias maneras, por ejemplo, enviando mensajes a un pequeño DB que su aplicación extraerá periódicamente. O registrar este componente en la máquina IIS (si existe) y exponer la simple API WS para comunicarse con ella.

Sé que puede sonar engorroso, pero las claras ventajas son: a) se comunica con Windows Search API utilizando el lenguaje que entiende (.NET o COM), b) controla todas las rutas de las aplicaciones.

+0

Realmente he pensado en la segunda opción, usando ws. Conozco algunos frameworks/servidores web ligeros de java que podrían usarse, no sé si hay algo más que IIS para el mismo propósito. IIS es un servidor web completamente actualizado, mientras que todo lo que se necesita es una comunicación http básica. – OscarRyz

+0

hay muchos servidores Java ligeros, pero si entiendo su problema, necesita el.Código NET (no Java) para ejecutar en el servidor web, por lo que IIS sería la primera y más simple opción – LiorH

+0

Hey Lior, Aunque tendería a estar de acuerdo contigo si esto es algo más complicado, creo que esto es bastante simple (solo una llamada OLE DB), como tal, creo que una llamada Java/COM no debería ser un problema. Sin embargo, he estado leyendo sobre esto, y parece que la integración de Java-COM puede ser una pesadilla, especialmente si entra en juego el enhebrado (por ejemplo, múltiples hilos de Java que comparten un objeto COM). –