Pergunta

Eu gostaria de entrar para consultar o serviço Windows Vista Pesquisa diretamente (ou indiretamente) do Java.

Eu sei que é possível consulta usando a busca-MS: protocolo, mas eu gostaria de consumir o resultado dentro do aplicativo

.

Eu encontrei uma boa informação no Windows Search API mas nenhum relacionado com Java.

Eu marcaria como aceite a resposta que fornece informações úteis e definitiva sobre a forma de alcançar este objectivo.

Agradecemos antecipadamente.

Editar

Alguém tem uma amostra de Jacó, antes que eu possa marcar este como aceite? :)

Foi útil?

Solução

Você pode querer olhar para uma das tecnologias de integração Java-COM. Eu pessoalmente tenho trabalhado com JACOB (COM Java Bridge):

O que era bastante pesado (acho que trabalha exclusivamente com a reflexão), mas obteve o trabalho feito por mim (prova rápida de conceito, acessando o MapPoint de dentro Java).

O único outro tipo de tecnologia Estou ciente de Jawin, mas eu não tenho nenhuma experiência pessoal com ele:

Atualização 2009/04/26: Apenas para os pedaços dele, eu fiz mais pesquisas sobre Microsoft Windows Search, e encontrou uma maneira fácil de integrar com ele usando OLE DB. Aqui está algum código que eu escrevi como uma prova de conceito:

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 isso, você precisa ter certeza de que o JAR JAWIN está em seu caminho de classe, e que jawin.dll está em seu caminho (ou propriedade do sistema java.library.path). Este código simplesmente abre uma conexão ADO com o índice Windows Desktop Search local, consultas de documentos com a palavra-chave "Foo", e imprimir algumas propriedades-chave nos documentos resultantes.

Deixe-me saber se você tem alguma dúvida ou precisa de mim para esclarecer qualquer coisa.

Atualização 2009/04/27: Eu tentei implementar a mesma coisa em JACOB, bem como, e vai fazer alguns benchmarks para comparar diferenças de desempenho entre os dois. Eu possa estar fazendo algo errado em Jacó, mas parece ser consistentemente usando 10x mais memória. Eu vou estar trabalhando em uma implementação JCOM e com4j, bem como, se eu tiver algum tempo, e tentar descobrir algumas peculiaridades que eu acredito que são devidos à falta de algum lugar a segurança do thread. Posso até tentar uma solução baseada JNI. Espero ser feito com tudo em 6-8 semanas.

Atualização 2009/04/28: Esta é apenas uma atualização para aqueles que tenho acompanhado e curioso. Acontece que não há problemas de threading, eu só precisava para fechar explicitamente os meus recursos de banco de dados, uma vez que as conexões OLE DB são, presumivelmente, agrupados no nível do OS (eu provavelmente deveria ter fechado as conexões de qualquer maneira ...). Eu não acho que eu vou ser quaisquer outras actualizações deste. Deixe-me saber se alguém é executado em quaisquer problemas com isso.

Atualização 05/01/2009: Adicionado JACOB exemplo por solicitação do Oscar. Isso passa pela mesma sequência exata de chamadas a partir de uma perspectiva COM, apenas usando JACOB. Embora seja verdade JACOB tem sido trabalhado muito mais ativamente em nos últimos tempos, eu também notar que é completamente um devorador de memória (usos 10x tanta memória quanto a versão 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();
        }
    }
}

Outras dicas

Como alguns posts aqui sugiro que você pode fazer a ponte entre Java e .NET ou COM utilizando estruturas comerciais ou gratuitos como Jacó, JNBridge, J-Integra etc .. Na verdade, eu tive uma experiência com com um desses terceiros (um caro :-)) e devo dizer que eu vou fazer o meu melhor para evitar repetir esse erro no futuro. A razão é que ela envolve muitas coisas "voodoo" você não pode realmente depuração, é muito complicado de entender o que é o problema quando as coisas dão errado.

A solução que eu sugiro que você implementar é a criação de um aplicativo .NET simples que faz com que as chamadas reais para os Windows Search API. Após fazer isso, você precisa estabelecer um canal de comunicação entre esse componente e seu código Java. Isso pode ser feito de várias maneiras, por exemplo, de mensagens para um pequeno banco de dados que sua aplicação vai periodicamente puxar. Ou registrar este componente na máquina IIS (se houver) e expô simples API WS se comunicar com ele.

Eu sei que pode soar complicado, mas as claras vantagens são: a) você se comunica com o Windows Search API usando a linguagem que ele entende (.NET ou COM), b) você controlar todos os caminhos de aplicação

.

Qualquer razão para que você não pode apenas usar Runtime.exec() para consulta via search-ms e ler o BufferedReader com o resultado do comando? Por exemplo:

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

Existem várias bibliotecas lá para chamar COM fora objetos de java, alguns são opensource (mas sua curva de aprendizado é maior) alguns são de código fechado e tem uma curva mais rápido aprendizado. Um exemplo de fonte fechada é EZcom . Os comerciais tendem a se concentrar em chamar java das janelas, bem como, algo que eu nunca vi em opensource.

No seu caso, o que eu sugiro que você faça é frente a chamada em sua própria classe .NET (acho que o uso C # como que está mais próximo Java sem entrar na polêmica J #), e foco em tornar a interoperabilidade com o .NET dll. Dessa forma, a programação do Windows fica mais fácil, ea interface entre o Windows e java é mais simples.

Se você está procurando para saber como usar uma biblioteca java com, o MSDN é o lugar errado. Mas o MSDN irá ajudá-lo a escrever o que você precisa dentro de .NET, e depois olhar para os tutoriais de biblioteca com cerca de invocar um ou dois métodos que você precisa de seus objetos .NET.

EDIT:

Dada a discussão nas respostas sobre como usar um Web Service, você pode (e provavelmente terá melhor sorte) construir um aplicativo .NET pequena que chama um servidor web java incorporado em vez de tentar fazer .NET tem o serviço de web embutido e ter java ser o consumidor da chamada. Para um servidor web embutido, minha pesquisa mostrou Winstone para ser bom. Não é o menor, mas é muito mais flexível.

O caminho para chegar a esse trabalho é iniciar o aplicativo .NET de java, e ter o aplicativo .NET chamar o serviço web em um temporizador ou um loop para ver se há um pedido, e se houver, processo -lo e enviar a resposta.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top