Acessando Código não Gerenciado a partir do Visual Basic .Net

Muito tem se falado sobre .Net, código gerenciado e não gerenciado, e ainda persistem algumas dúvidas sobre o que exatamente cada um destes termos significa; portanto, vamos antes de mais nada esclarecer alguns termos.

O que é a .Net Framework

Segundo a Microsoft, a mudança do Windows para o .Net é uma mudança tão grande quanto a que houve quando se mudou do DOS para o Windows.  Não se trata de apenas uma mudança na versão das linguagens (do Visual Studio 6.0 para o Visual Studio .Net), mas a criação de todo um novo paradigma de ambiente, serviços e servidores, o que obviamente impacta na criação de programas e como eles interagem.

A figura 1 apresenta uma visão geral dos diversos componentes da plataforma Windows e da nova plataforma .Net.

Figura 1: As Plataformas Windows e .Net

Uma das grandes mudanças a nível de programas na plataforma .Net é que cada programa roda na sua própria “sandbox”, ou “caixa de areia”, o que significa que cada programa é isolado dos demais. 

Devido ao fato do programa ser controlado externamente para evitar que ele faça qualquer operação indevida que afete outros programas, dizemos que os programas que rodam sobre a plataforma .Net são “gerenciados”, e os programas na plataforma antiga, por conseqüência, “não-gerenciados”.  O fato de um programa ser ou não gerenciado impacta diretamente nos direitos que este programa tem sobre o sistema – todo programa não-gerenciado é, como padrão, “não confiável”.

Vivendo um momento de transição

No entanto, este mundo ideal onde o próprio sistema operacional será gerenciado ainda não está totalmente disponível, motivo pelo qual nossos programas, mesmo os criados no Visual Studio .Net, precisarão ainda por vezes acessar código não gerenciado.

Existem basicamente dois tipos de código não gerenciado que nossos programas podem querer acessar:  Componentes COM+, criados em versões anteriores do Visual Studio, ou bibliotecas de ligação dinâmica (DLLs), do Windows ou de terceiros.

O acesso a componentes COM+ é extremamente facilitado, pois o Visual Studio .Net permite que se criem referências a este tipo de componentes.  Uma vez criada a referência, o Visual Studio .Net cria uma classe “wrapper”, que encapsula as chamadas ao COM+ e as transforma em chamadas gerenciadas, para serem utilizadas diretamente por nossos programas.  Por este motivo, neste artigo nos concentramos no acesso a DLLs.

A .Net Framework oferece aos programas criados no Visual Studio uma interface gerenciada que substitui as antigas chamadas a APIs do Windows.   Porém, como nem todas APIs estão mapeadas em classes, precisaremos eventualmente acessar diretamente as DLLs.  Por exemplo, alguns membros da DLL WinMM.DLL, responsável pelo controle de multimedia no Windows, não tem classes correspondentes na atual versão da .Net Framework.

Acessando Código não-Gerenciado

Embora internamente o processo de chamar uma DLL não gerenciada a partir de um programa gerenciado requeira uma série de passos, nem todos simples, o Visual Basic .Net manteve esta interface simples para os programadores, permitindo que as DLLs fossem declaradas para uso em um programa de duas maneiras diferentes.

A primeira das maneira é a forma “clássica”, já utilizada nas versões anteriores do Visual Basic: declarar a função, a DLL de origem, seus parâmetros e valores de retorno através do comando Declare, como mostrado no seguinte exemplo, para a função utilizada para reproduzir arquivos de som padrão WAV:

Declare Function sndPlaySoundA Lib "winmm.dll"(lpszSoundName As String, uFlags As Integer) As Integer

O Visual Basic .Net introduz uma nova maneira de realizar esta declaração, usando um atributo declarativo que informa à aplicação que a função a ser usada na verdade reside em uma DLL não gerenciada, fora do mundo .Net.   Esta nova forma é a sugerida como preferencial para declarar funções em DLLs.  A sintaxe para esta declaração é idêntica à declaração de uma função usual do Visual Basic, com a diferença que a função deve ficar vazia e seu nome deve vir precedido do atributo declarativo DLLImport, seguido do nome da DLL, como podemos ver no próximo exemplo de código.

<DllImport("winmm.dll")>Function sndPlaySoundA(lpszSoundName As String, uFlags As Integer)As Integer

    'Esta função deve ficar vazia, pois está implementada em uma DLL.

End Function

O uso de atributos declarativos é uma inovação no Visual Studio .Net, que pode ser utilizada para diversos fins, como “assinar” seu programa incluindo atributos com o nome do autor, adicionar informações extras para uso externo ou interno (como, por exemplo, o nome de fontes de dados ODBC que devem ser criadas); e até mesmo tornar nosso código mais seguro contra vírus, pois determinados atributos especiais permitem indicar que recursos do sistema operacional o programa pode ou não usar – o que evita que um vírus usasse recursos que não estavam previstos pelo criador do programa infectado.  Consulte a ajuda on-line do Visual Studio para mais informações sobre atributos declarativos.

Uma vez que a função que desejamos utilizar está declarada, de uma das duas maneiras descritas acima, podemos chamar a função diretamente, como se fosse uma função escrita em nosso próprio programa.  O exemplo a seguir mostra um código completo que permite a reprodução de um arquivo WAV, incluindo declarações de constantes para tornar o código mais claro.

<DllImport("winmm.dll")>Function sndPlaySoundA(lpszSoundName As String, uFlags As Integer)As Integer

   'Esta função deve ficar vazia, pois está implementada em uma DLL.

End Function

Const SND_SYNC =&H0

Const SND_ASYNC =&H1

Const SND_NODEFAULT =&H2

Const SND_LOOP =&H8

Const SND_NOSTOP =&H10

Const SND_PURGE =&H40

Public Sub Main()

   Dim strNomeArquivo As String ="C:\temp\BEEP.Wav"

   sndPlaySoundA(strNomeArquivo,SND_ASYNC Or SND_NODEFAULT)

End Sub

 

Baixe o código deste artigo aqui!

Voltar