VB .NET - Chamando a API do Windows (Win 32 API)


Às vezes para realizar uma tarefa na linguagem VB .NET precisamos usar recursos de terceiros, e, apesar da grande quantidade de recursos disponíveis nas classes, métodos e propriedades da linguagem ainda existem algumas funções disponíveis na API do Windows(Win 32 API) que preenchem uma lacuna existente.

A plataforma .NET é baseada no código gerenciado e às vezes por este motivo não é possível realizar algumas tarefas como obter informações sobre os drives locais, etc. Se você precisar de informações como espaço livre em termos de bytes ou clusters pode usar as funções GetDiskFreeSpaceEx e GetDiskFreeSpace da API do Windows. (Você pode até usar os recursos de My.Computer.FileSystem.GetDriveInfo mas algumas informações não estão disponíveis.)

A API Win32 é muito útil tanto para aplicações Desktop como para aplicações ASP .NET lembrando que no último caso a API opera sempre sobre o servidor e não na máquina do cliente, e, que as chamadas à Win 32 API não são permitidas no SilverLight 3 e SilverLight 4.(Se você tentar chamar a API em aplicações SilverLight via obter a mensagem de erro: "Attempt by security transparent method 'Button1Click' to call native code through method 'Win32APIMethod' failed. Methods must be security critical or security safe-critical to call native code.")

O interessante é que a API Win 32 esta disponível para sua aplicação VB .NET sem que seja preciso incluir qualquer referência, e, como já foi dito, embora a maioria dos recursos presentes na API estejam disponíveis na plataforma .NET Framework ainda existem alguns recursos ou funcionalidades estendidas que existem somente na API.

Se você deseja conhecer mais sobre os recursos da API Win 32 sugiro que veja o artigo: Microsoft Win32 to Microsoft .NET Framework API Map.

Para ilustrar a utilização da API Win 32 em aplicações VB .NET , neste artigo eu vou mostrar como usar os recursos para obter informações sobre os drivers, como podemos colocar o computador para hibernar e como obter a versão do sistema operacional.

Vamos lá...

1- Obtendo informações sobre os drivers locais

Abra o Visual Studio 2010 Express Edition e crie um novo projeto do tipo Windows Application com o nome ChamandoWinAPI;

No formulário padrão inclua um controle Button e um controle ListView conforme o leiaute da figura abaixo:

A seguir inclua o código a seguir:

a- função DiskInfo() que faz a chamada a API Win32 para obter as informações dos drives locais:

    Private Sub DiskInfo()

        Dim RootPath As String = "C:\"
        Dim SectorsInCluster As Integer = 0
        Dim BytesInSector As Integer = 0
        Dim NumberFreeClusters = 0
        Dim TotalNumberClusters = 0
        Call Win32API.GetDiskFreeSpace(RootPath, SectorsInCluster, BytesInSector,NumberFreeClusters, TotalNumberClusters)

        ListBox1.Items.Add("GetDiskSpace: Cluster livres em C: " & NumberFreeClusters)

        Dim FreeBytes As Integer = 0
        Dim TotalBytes As Integer = 0
        Dim TotalFreeBytes As UInt32 = 0
        Call Win32API.GetDiskFreeSpaceEx(RootPath, FreeBytes, TotalBytes, TotalFreeBytes)

        ListBox1.Items.Add("GetDiskSpaceEx: Total de bytes livres em C : " & TotalFreeBytes)

        Dim DriveType As Integer = Win32API.GetDriveType(RootPath)
        Dim DriveTypeName As String = String.Empty
        Select Case DriveType
            Case 2 : DriveTypeName = "Removível"
            Case 3 : DriveTypeName = "Fixo"
            Case 4 : DriveTypeName = "Remoto"
            Case 5 : DriveTypeName = "CD-Rom"
            Case 6 : DriveTypeName = "RAM Disk"
            Case Else : DriveTypeName = "Desconhecido"
        End Select

        ListBox1.Items.Add("GetDriveType: Tipo de Drive : " & DriveTypeName)
    End Sub

b- A declaração das funções da API

Partial Public Class Win32API

        Public Declare Function GetDiskFreeSpace Lib "kernel32" _
            Alias "GetDiskFreeSpaceA" (ByVal RootPathName As String,
                                                     ByRef SectorsPerCluster As Integer,
                                                     ByRef BytesPerSector As Integer,
                                                     ByRef NumberOfFreeClusters As Integer,
                                                     ByRef TotalNumberOfClusters As Integer) As Integer

        Public Declare Function GetDiskFreeSpaceEx Lib "kernel32" _
            Alias "GetDiskFreeSpaceExA" (ByVal RootPathName As String,
                                                         ByRef FreeBytesAvailableToCaller As Integer,
                                                         ByRef TotalNumberOfBytes As Integer,
                                                         ByRef TotalNumberOfFreeBytes As UInt32) As Integer

        Public Declare Function GetDriveType Lib "kernel32" _
             Alias "GetDriveTypeA" (ByVal nDrive As String) As Integer

    End Class

A chamada à função DiskInfo() é feita no evento Click do controle Button:

 Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        Call DiskInfo()
    End Sub

Executando o projeto iremos obter (no caso da minha máquina local):

Partial Classes - Lembre-se que no VB.NET quando você vai definir uma classe você cria um arquivo com extensão .vb e ele irá conter a classe completa em um único arquivo; desta forma você inicia e termina a classe no mesmo arquivo físico. Ex: Classe1.vb

Usando o conceito de partial class você pode separar o código de uma classe em mais de um arquivo físico.

2- Fazendo o computador hibernar

Podemos fazer o computador hibernar usando a função IsPwrHibernateAllowed da library Powrprof.dll que retorna um valor true (não zero) se a hibernação é permitida ou false (zero) se a hibernação é permitida. Se ela for permitida a função SetSuspendState pode ser chamada para ativar a hibernação.

Inclua um novo botão no formulário do projeto e a seguir inclua o código abaixo que declara a função da API que vamos usar:

 Partial Public Class Win32API

        Public Declare Function IsPwrHibernateAllowed Lib "Powrprof.dll"  Alias "IsPwrHibernateAllowed" () As Integer

        Public Declare Function SetSuspendState Lib "Powrprof.dll"  Alias "SetSuspendState" (ByVal Hibernate As Integer,
                                                                                                                                     ByVal ForceCritical As Integer,
                                                                                                                                     ByVal DisableWakeEvent As Integer) As Integer

    End Class

Em seguida inclua no evento Click do botão de comando o código que chama a API:

 Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
        If (Win32API.IsPwrHibernateAllowed() <> 0) Then
            Win32API.SetSuspendState(1, 0, 0)
        Else
            MessageBox.Show("A hibernação não esta disponível.")
        End If
    End Sub

3- Obtendo a versão do sistema Operacional

Para obter a versão do sistema operacional chamamos a função GetVersionEx.

Inclua um novo controle Button no formulário e declare a estrutura e a função da API que vamos usar no formulário:

 Public Structure OSVersionInfo
        Public OSVersionInfoSize As Integer
        Public majorVersion As Integer
        Public minorVersion As Integer
        Public buildNumber As Integer
        Public platformId As Integer
        <MarshalAs(UnmanagedType.ByValTStr, SizeConst:=128)> _
        Public versionString As String
    End Structure

    Declare Ansi Function GetVersionEx Lib "kernel32.dll" _
     Alias "GetVersionExA" (ByRef osvi As OSVersionInfo) As Boolean

Em seguida no evento Click do botão de comando inclua o código abaixo:

Private Sub Button3_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button3.Click
        Dim osvi As New OSVersionInfo
        osvi.OSVersionInfoSize = Marshal.SizeOf(osvi)

        If GetVersionEx(osvi) Then
            Dim resultado As String =
                String.Format("Versão do Windows : {0}.{1}.{2}.{3}",
                osvi.majorVersion, osvi.minorVersion,
                osvi.buildNumber, osvi.platformId)
            ListBox1.Items.Add(resultado)
        End If

    End Sub

Executando o projeto iremos obter:

Pegue o projeto completo aqui:  ChamandoWinAPI_1.zip

Eu sei é apenas VB .NET , mas eu gosto...

Referências:


José Carlos Macoratti