Exécuter du code vb.net à partir d'un programme en cours d'exécution

Contenu du snippet

Ce programme à pour but de montrer comment on peut exécuter du code vb.net (ou c#) pendant l'exécution.

Ce n'est qu'une façon de procéder parmi d'autres.

Pour pouvoir tester ce code il faut :
  • Créer un formulaire sur lequel on place 2 objets :

- un bouton appelé cmdExec
- un RichTextBox appelé RTB
  • Créer une class appelée DynamicCode


Si vous souhaitez ajouter une référence à votre code qui est en cours d'exécution il faut l'ajouter au paramètre CP comme suit :
CP.ReferencedAssemblies.Add(System.Reflection.Assembly.GetExecutingAssembly.Location)
Dans ce cas, il ne faut pas oublié d'ajouter les références liées à votre projet. Exemple :
CP.ReferencedAssemblies.Add("System.Windows.Forms.dll")

Pour intégrer une gestion d'erreur il faut stocker les messages car il peut y en avoir plusieur à suivre dans la procedure de compilation. On pourrait la retravailler comme suit :
Dim CR As CodeDom.Compiler.CompilerResults = CDP.CompileAssemblyFromSource(CP, sCodeSource)
Try
Return CR.CompiledAssembly
Catch ex As Exception
For i As Integer = 0 To CR.Errors.Count - 1
'procedure contenant un RichTextBox sur lequel on ajoute les messages d'erreur
addMessage(CR.Errors.Item(i).ErrorText)
Next
Return Nothing
End Try

Source / Exemple :


Public Class DynamicCode
    ''' <summary>
    ''' Compilation de code vb.net
    ''' </summary>
    ''' <param name="sCodeSource">code source</param>
    ''' <returns>assembly</returns>
    ''' <remarks>nécessite le chargement de l'assembly pour l'exécution</remarks>
    Public Shared Function compile(ByVal sCodeSource As String) As System.Reflection.Assembly
        Dim CP As CodeDom.Compiler.CompilerParameters = New CodeDom.Compiler.CompilerParameters()
        CP.ReferencedAssemblies.Add("System.dll")
        CP.GenerateExecutable = False
        Return compile(CP, sCodeSource)
    End Function

    ''' <summary>
    ''' Compilation de code vb.net
    ''' </summary>
    ''' <param name="CP">imports, génération d'exe ...etc</param>
    ''' <param name="sCodeSource">code source</param>
    ''' <returns>assembly</returns>
    ''' <remarks>nécessite le chargement de l'assembly pour l'exécution</remarks>
    Public Shared Function compile(ByVal CP As CodeDom.Compiler.CompilerParameters, ByVal sCodeSource As String) As System.Reflection.Assembly
        Dim CDP As CodeDom.Compiler.CodeDomProvider = New VBCodeProvider()
        Return compile(CDP, CP, sCodeSource)
    End Function

    ''' <summary>
    ''' compilation de code
    ''' </summary>
    ''' <param name="CDP">vb.net, c# ou autre</param>
    ''' <param name="CP">imports, génération d'exe ...etc</param>
    ''' <param name="sCodeSource">code source</param>
    ''' <returns>assembly</returns>
    ''' <remarks>nécessite le chargement de l'assembly pour l'exécution</remarks>
    Public Shared Function compile(ByVal CDP As CodeDom.Compiler.CodeDomProvider, ByVal CP As CodeDom.Compiler.CompilerParameters, _
            ByVal sCodeSource As String) As System.Reflection.Assembly
        Dim CR As CodeDom.Compiler.CompilerResults = CDP.CompileAssemblyFromSource(CP, sCodeSource)
        Return CR.CompiledAssembly
    End Function
End Class

'----------------------------------------
'Code à mettre dans le formulaire
Private Sub cmdExec_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles cmdExec.Click
            execCode()
        End Sub

        Private Sub execCode()
            Me.cmdExec.Enabled = False
            Dim TH As New Threading.Thread(AddressOf execCodeTH)
            TH.Start()
        End Sub

        Private Sub execCodeTH()
            Try
                Threading.Thread.Sleep(1)
                Dim S As String = "Imports System" & vbCrLf & "Class TestClass" & vbCrLf & "Public Shared Sub testSub()" & vbCrLf
                S &= RTB.Text
                S &= vbCrLf & "End Sub" & vbCrLf & "End Class"
                Dim A As System.Reflection.Assembly = DynamicCode.compile(S)
                If Not A Is Nothing Then
                    Dim T As Type = A.GetType("TestClass")
                    Dim M As System.Reflection.MethodInfo = T.GetMethod("testSub")
                    M.Invoke(Nothing, Nothing)
                End If
            Catch ex As Exception
                'Gestion d'erreur à faire en fonction de votre programme
                msgbox(ex.Message)
            End Try
            Me.cmdExec.Enabled = True
        End Sub
'----------------------------------------

Conclusion :


Le choix est ici porté sur l'exécution directe du code
Mais on peut très bien choisir de tout rendre paramétrable (Namespace, Class, Sub etc...)

Pour tester on peut exécuter la commande suivante (en ayant un fichier C:\A.txt) :
System.IO.File.Copy("C:\A.txt","C:\B.txt")

A voir également

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.