Original Article: Python and COM
Author: Paul Boddie

Python and COM

Home Pessoas COM Emulação
Python

Resumo

Tenho jogado com Python e COM no Windows 2000. Embora a ajuda incorporada no PythonWin vá de alguma forma para explicar os detalhes estranhos da COM e das várias interfaces comuns que se pode encontrar, é realmente necessário procurar uma interface concreta em formação. Existem algumas fontes de tais informações, e o objetivo deste documento é ajudar os leitores a usar tais fontes, ou mesmo a ajudá-los a evitar a necessidade de usar essas fontes.

Pré-requisitos

Talvez a maneira mais fácil de obter plataformas Python para Windows é ir para o ActiveState e baixar seu pacote ActivePython. Você pode, alternativamente, visitar o site Python, baixar o Python (consulte o suporte Python para a página do Windows) e depois procurar as extensões win32all consulte a página Python para Extensões do Windows de Mark Hammond para obter detalhes). Eu simplesmente fiz o que foi mais fácil, é claro!

Para as atividades a seguir, você pode precisar de software adicional, como o Microsoft Outlook, embora você provavelmente não esteja interessado em jogar com o Outlook e o Exchange, se você não possui.

Outlook e Exchange

Uma das coisas supostamente irritantes sobre o Microsoft Exchange Server é a forma como ele oculta muitos dos seus internos e exige uma quantidade razoável de programação para que você possa chegar a coisas como listas de contatos e livros de endereços. É interessante notar que é necessário encontrar muitos conselhos sobre como importar os livros de endereços de outros sistemas para o Exchange, mas não tanto em obter as endereços de volta e em outra coisa. Felizmente, a Microsoft fornece o suficiente de uma API para se tornar sua própria "destruição", uma vez que esta API fornece um mecanismo razoável para acessar os internos e extrair a informação encriptada.

De qualquer forma, isso me levou a escrever um pequeno programa para acessar listas de mensagens, contatos e compromissos do Exchange através do Outlook. Se sua organização estiver executando o Exchange, provavelmente você também precisa executar o Outlook e, portanto, automatizar o Outlook é uma estratégia válida para acessar o Exchange. Uma alternativa para acessar certos tipos de informações é usar a API dos Serviços do Active Directory e/ou o LDAP, mas não fui bem sucedido naquela área.

Exemplo: Outlook Explorer

Nota: Antes de iniciar esta aplicação, crie "Microsoft Outlook 9.0 Object Library" usando o "COM Makepy utility" (consulte "Initialising Type Libraries").

O programa Outlook Explorer (que você pode fazer o download) usa MAPI (Messaging API) no Outlook para acessar recursos de email. Você pode navegar a hierarquia de objetos usando uma interface de linha de comando simples e extrair informações para diretórios existentes no sistema de arquivos.

Atividades

Inicializando bibliotecas de tipos

Embora o pacote win32com forneça várias maneiras de consultar e acessar interfaces COM com poucas diferenças óbvias entre elas (desde que conheça a interface), geralmente é mais conveniente ao experimentar (particularmente no PythonWin com seu recurso de conclusão de atributos) para saber quais métodos e as propriedades estão realmente disponíveis para uma determinada interface. Aqui é útil o utilitário "COM Makepy", acessível no menu "Ferramentas" no PythonWin. Ao selecionar uma biblioteca de tipos específicos e construir as interfaces Python usando esta ferramenta, muito mais informações ficam disponíveis no PythonWin, e a investigação casual das interfaces de objetos torna-se muito fácil.

Escrevendo clientes

Todo o acesso COM do cliente começa com a seguinte declaração no seu programa Python:

import win32com.client

Normalmente, seu programa tentará e achará um objeto a ser usado. Por exemplo:

object = win32com.client.Dispatch("Outlook.Application")

Este objeto então se referirá a um "objeto COM" que pode ter métodos invocados sobre ele e seus atributos examinados como qualquer outro objeto Python, embora possamos estar "automatizando" um aplicativo do Windows (como o Outlook) quando fazemos isso.

Encontrando a Raiz de Hierarquia de Objetos

Uma vez que temos uma referência a um objeto que está "automatizando" um aplicativo, a próxima coisa a fazer é encontrar a raiz da hierarquia de objetos onde todas as informações interessantes são armazenadas. Com o objeto de automação do aplicativo Outlook, a maneira mais fácil de conseguir isso é inserir o namespace MAPI:

ns = object.GetNamespace("MAPI")

Isso nos permite acessar a hierarquia "pasta" acessível no Outlook. Você pode ver esta hierarquia, abrindo o Outlook manualmente e trazendo o menu da pasta (que tipicamente diz "Caixa de entrada" ou "Outlook hoje" ou algo assim).

O objeto ns agora pode ser tratado como um objeto Python normal, com atributos especiais que levam a outras partes da hierarquia de objetos.

Pastas e Itens

O programa do Outlook Explorer usa alguns truques sofisticados do Python para acessar os atributos dos "objetos COM" que ele faz referência, mas na essência procura as pastas e itens disponíveis em cada objeto:

# Refer para as pastas com um dado objeto...
ns_list = ns.Folders
# Refer para os itens com um dado objeto...
ns_list = ns.Items

Consultando Interfaces

Agora, como investigar o detalhe de cada objeto? Por exemplo, como um acessa o nome de uma pasta? Em primeiro lugar, ajuda a conhecer a interface que o objeto expõe, e essa informação pode ser encontrada em vários locais:

  • A documentação da API da Microsoft.
  • Outras fontes úteis, como a documentação do "Outlook Exchange".
  • O arquivo de interface gerado pelo "utilitário COM Makepy". Para saber qual arquivo é relevante para a interface em questão, execute uma pesquisa "grep" para o nome da interface no diretório win32com/gen_py dentro da sua distribuição Python, ou invoque um método incorreto ou acesse um atributo inexistente em um se aponte para essa interface para ver qual é o nome do arquivo da interface.
  • O "OLE / COM Object Viewer" no menu "Ferramentas" no Microsoft Visual C ++ (pelo menos no Visual Studio 6.
    • Uma vez aberta, a seção "Interfaces" da hierarquia de informações pode ser explorada para revelar algumas entradas "_Application". Para um desses, o painel de informações mencionará "Microsoft Outlook 9.0 Object Library" em "TypeLib", por exemplo.
    • Clicando duas vezes em uma entrada "_Application" fornecerá um "ITypeInfo Viewer" que contém uma seção "_Methods" descrevendo os métodos disponíveis no objeto de automação do aplicativo.
    • A seção "Bibliotecas de tipos" da hierarquia de informações listará, por exemplo, "Microsoft Outlook 9.0 Object Library", e isso pode ser investigado clicando duas vezes naquela entrada.

Felizmente, no entanto, o objeto que você está acessando é conhecido o bastante pela PythonWin para permitir algum tipo de atributo ou conclusão do método nele. Você só precisa recorrer ao acima quando um conhecimento mais detalhado sobre um método ou atributo é necessário. Você também pode tentar algo como:

dir(object.__class__)

O nome de uma pasta pode ser acessado da seguinte maneira:

Object.nome # onde o objeto refere-se a uma pasta.

Sequências

Claro, pode haver muitas pastas ou itens em uma pasta. Como atravessamos essa coleção? A maneira recomendada é argumentar usar a notação do índice de seqüência do Python, mas cuidado: o índice do primeiro elemento aparentemente não é padrão e pode ser 0 ou 1. No modelo de objeto do Outlook, o primeiro elemento em tais sequências é de fato indexado por 1, resultando no seguintes observações:

  • O comprimento da seqüência, enquanto correto, não pode ser "diminuído" para fornecer o índice do último elemento. Por exemplo, se len(object)34, então o último elemento não tem o índice 33 - tem o índice 34. Muito não-Pythonic, podemos reivindicar, mas aparentemente não há nada que realmente possa ser feito sobre isso.
  • O "primeiro elemento Pythonic" (elemento 0) não existe.

Para acessar objetos que se comportam como seqüências, os seguintes mecanismos Python podem ser usados:

object[1]   # O primeiro elemento.
len(object) # Retornar o número de elementos.

Os seguintes mecanismos não parecem funcionar:

object[-1]  # Deve ser o último elemento, mas em vez disso, obtém uma exceção.
object[1:4] # Deve cortar a sequência, mas em vez disso, obtém uma exceção.

Resumo

Com as informações acima, o programa de exemplo pode acessar diferentes níveis de pastas, itens de consulta e extrair informações. Ao usar o atributo Parent em qualquer pasta, podemos navegar para cima através da hierarquia sem precisar manter referências a locais que já exploramos.