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")
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.