VB .NET - Lendo, compilando e executando um arquivo texto


Você já precisou ler , compilar e executar um arquivo texto ??

Como assim ???

Deixa eu explicar melhor...

Vamos supor que você tenha um arquivo texto e esse arquivo contém um código VB .NET válido.

Vamos supor também que você tem que ler o arquivo compilar e executar o código e exibir o resultado em uma aplicação VB .NET.

Como você poderia resolver este problema ?

Isto eu vou mostrar neste artigo...

Para fazer isso vamos ter que usar a classe VBCodeProvider.

Esta classe fornece acesso às instâncias do gerador de código de Visual Basic e do compilador de código.

Vamos então ao projeto

Criando o projeto no VB .NET

Abra o Visual Basic 2010 Express Edition e crie um novo projeto do tipo (menu File-> New Project) Windows Forms com o nome CompiladorVB;

No formulário padrão vamos incluir os seguintes controles:

O leiaute do formulário deverá ter o seguinte aspecto:

Como exemplo vamos usar um código VB .NET bem simples em um arquivo texto.

Vamos incluir um arquivo texto no projeto.

Clique com o botão direito do mouse sobre o projeto e selecione Add New Item;

A seguir selecione o template Text File e informe o nome Codigo1.txt e clique em Add;

Feito isso clique duas vezes com o mouse sobre o arquivo Codigo1.txt na janela Solution Explorer para abrí-lo no Editor e digite o código conforme mostra a figura a seguir:

O código VB .NET do arquivo vai realizar uma interação usando um laço For/Next e calcular a soma retornando o valor para o controle TextBox txtResultado.txt;

Vamos agora declarar os namespaces que iremos precisar no formulário para realizar a tarefa:

Imports System.IO
Imports System.Reflection
Imports System.CodeDom
Imports System.CodeDom.Compiler
Imports Microsoft.VisualBasic
Imports System.Globalization

O namespace System.CodeDom contém classes que podem ser usadas para representar os elementos e a estrutura de um documento de código-fonte.

As classes neste namespace podem ser usadas para modelar a estrutura de um documento código-fonte que pode ser a saída como código-fonte em uma linguagem suportada usando a funcionalidade fornecida pelo namespace System.CodeDom.Compiler.

Vamos agora definir o código do evento Click do botão de comando conforme abaixo:

 Private Sub btnLerExecutar_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) 
Handles btnLerExecutar.Click

        Dim entrada As String

        Try
            ' Lê o codigo do arquivo texto
            entrada = My.Computer.FileSystem.ReadAllText("Codigo1.txt")
        Catch ex As Exception
            MessageBox.Show(" Erro : " + ex.Message)
            Return
        End Try

        ' Cria o 'codigo' literal para passar para o compilar
        '
        ' Note que usamos  o codigo <% = entrada % > onde o código lido
        ' é inserido no fragmento de código
        Dim codigo = <code>
                       Imports System
                       Imports System.Windows.Forms

                       Public Class TempClass
                           Public Sub ResultadoTexto(ByVal txtOutput As TextBox)
                               <%= entrada %>
                           End Sub
                       End Class
                   </code>
        Try
            ' Cria o compilador VB.NET
            Dim vbProv = New VBCodeProvider()
            ' Cria os parametros apra passar para o compilador
            Dim vbParams = New CompilerParameters()
            ' Inclui as referencias aso assemblies.
            vbParams.ReferencedAssemblies.Add("mscorlib.dll")
            vbParams.ReferencedAssemblies.Add("System.dll")
            vbParams.ReferencedAssemblies.Add("System.Windows.Forms.dll")
            vbParams.GenerateExecutable = False
            ' Garante que vamos gerar um assembly em memoria e não um arquivo fisico
            vbParams.GenerateInMemory = True
            ' Compila o código e obtem do compilador os resultados (incluindo erros, etc...)
            Dim resultadoCompilacao = vbProv.CompileAssemblyFromSource(vbParams, codigo.Value)
            ' verifica os erros do compilador
            If resultadoCompilacao.Errors.Count > 0 Then
                ' exibe cada erro
                For Each er In resultadoCompilacao.Errors
                    MessageBox.Show(er.ToString())
                Next
            Else
                ' Cria uma instância da classe compilada
                Dim obj As Object = resultadoCompilacao.CompiledAssembly.CreateInstance("TempClass")
                ' Um array de objetos que representa os argumentos a serem passados para o nosso método (txtOutPut)
                Dim args() As Object = {Me.txtOutPut}
                ' Executa o método passando o nome do método e os argumentos
                Dim t As Type = obj.GetType().InvokeMember("ResultadoTexto", BindingFlags.InvokeMethod, 
Nothing, obj, args)
            End If

        Catch ex As Exception
            MessageBox.Show("Erro : " + ex.Message)
        End Try
    End Sub

Como exemplo estamos usando o nome do arquivo texto fixo no código ( o arquio codigo1.txt esta na basta bin\Debug);

Executando o projeto iremos obter o resultado da compilação do código vb. net do arquivo texto Codigo1.txt:

Gerando um arquivo executável físico

Agora vamos continuar usar os recursos da classe VBCodeProvider para criar um arquivo .EXE a partir de um arquivo de código CSharp;

Inclua mais um controle Button no projeto com o nome igual a btnGerarExe e a seguir inclua o seguinte código no seu evento Click:

Private Sub btnGerarExe_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnGerarExe.Click
        CompilarExecutavel("Codigo1.cs")
        MessageBox.Show("Gerado com sucesso.")
    End Sub

A seguir vamos definir o código da função CompilarExecutavel:

 Public Shared Function CompilarExecutavel(ByVal nomeFonte As String) As Boolean
        Dim arquivoFonte As FileInfo = New FileInfo(nomeFonte)
        Dim provider As CodeDomProvider = Nothing
        Dim compileOk As Boolean = False

        ' Selecione o código baseado na extensão do arquivo
        If arquivoFonte.Extension.ToUpper(CultureInfo.InvariantCulture) = ".CS" Then
            provider = CodeDomProvider.CreateProvider("CSharp")
        ElseIf arquivoFonte.Extension.ToUpper(CultureInfo.InvariantCulture) = ".VB" Then
            provider = CodeDomProvider.CreateProvider("VisualBasic")
        Else
            MessageBox.Show("Arquivo de codigo deve ter uma extensão .cs ou .vb")
        End If

        If Not provider Is Nothing Then

            ' Formata o nome do arquivo executavel
            ' Construindo o caminho do assembly de saida no diretorio atual
            ' e <source>_cs.exe ou <source>_vb.exe.

            Dim exeName As String = String.Format("{0}\{1}.exe", _
                                                System.Environment.CurrentDirectory, _
                                                 arquivoFonte.Name.Replace(".", "_"))

            Dim cp As CompilerParameters = New CompilerParameters()

            ' Gera um executavael ao inves de um class library.
            cp.GenerateExecutable = True

            ' Especifica o nome do arquivo assembly a gerar
            cp.OutputAssembly = exeName

            ' Salva o  ssembly como um arquivo fisico
            cp.GenerateInMemory = False

            ' Trata os erros e avisos
            cp.TreatWarningsAsErrors = False

            ' Invoca a compilação do arquivo fonte
            Dim cr As CompilerResults = provider.CompileAssemblyFromFile(cp, nomeFonte)

            If cr.Errors.Count > 0 Then
                ' exibe as mensagens de erro
                MessageBox.Show("Erros Construindo " + nomeFonte + " em " + cr.PathToAssembly)

                Dim ce As CompilerError
                For Each ce In cr.Errors
                    MessageBox.Show("  {0}", ce.ToString())
                Next ce
            Else
                ' Exibe a mensagem de compilação com sucesso
                MessageBox.Show("Fonte " + nomeFonte + " foi construido com sucesso em " + cr.PathToAssembly)
            End If

            ' Retorna os resultadaos da compilação
            If cr.Errors.Count > 0 Then
                compileOk = False
            Else
                compileOk = True
            End If
        End If
        Return compileOk
    End Function

Agora vamos incluir um arquivo texto com o nome Codigo1.cs no projeto, na basta bin/Debug;

No menu Project-> Add New Item e selecione Text File informando o nome Codigo1.cs;

A seguir inclua o código abaixo neste arquivo:

using System;

namespace ConsoleTeste
{
    class Program
    {
        static void Main(string[] args)
        {
            int soma = 0;
            for (int i = 0; i == 20; i++)
            {
                soma += i;
            }
            Console.WriteLine(" Valor Soma : " + soma);
        }
    }
}

Agora só resta testar o código.

Executando o projeto teremos a mensagem sucesso na operação e

Abrindo a pasta indicada veremos o arquivo exe gerado:

Pegue o projeto completo aqui: CompiladorVB.zip

Rom 13:1 Toda alma esteja sujeita às autoridades superiores; porque não há autoridade que não venha de Deus; e as que existem foram ordenadas por Deus.
Rom 13:2
Por isso quem resiste à autoridade resiste à ordenação de Deus; e os que resistem trarão sobre si mesmos a condenação.
Rom 13:3
Porque os magistrados não são motivo de temor para os que fazem o bem, mas para os que fazem o mal. Queres tu, pois, não temer a autoridade? Faze o bem, e terás louvor dela;

Rom 13:4
porquanto ela é ministro de Deus para teu bem. Mas, se fizeres o mal, teme, pois não traz debalde a espada; porque é ministro de Deus, e vingador em ira contra aquele que pratica o mal.

Referências:


José Carlos Macoratti