Evaluer/executer une chaine en tant que code

Soyez le premier à donner votre avis sur cette source.

Vue 9 616 fois - Téléchargée 488 fois

Description

Cette source vous permettra d'exécuter une chaîne contenant du code source en VB.Net.
J'utilise CodeDom et la Reflection pour générer un assembly en mémoire, à la demande, et récupérer le résultat du code exécuté.

Comme exemple, j'ai monté une mini mini application de dessin, permettant de générer un menu Transformation avec des fichiers textes contenant le nom de la commande puis le code.

Source / Exemple :


''' <summary>
    ''' Cette fonction permet l'exécution d'une commande passée sous forme de chaîne.
    ''' </summary>
    ''' <param name="cmd">La commande à exécuter sur l'image.</param>
    ''' <param name="img">L'image d'origne.</param>
    ''' <returns>L'image transformée selon le code de "cmd".</returns>
    ''' <remarks></remarks>
    Private Function ExecuteCommand(ByVal cmd As String, ByVal img As Image) As Image
        Dim vbCodeProv As VBCodeProvider = New VBCodeProvider
        Dim cParam As CodeDom.Compiler.CompilerParameters = New CodeDom.Compiler.CompilerParameters

        ' Ajout des références
        cParam.ReferencedAssemblies.Add("System.dll")
        cParam.ReferencedAssemblies.Add("System.Drawing.dll")

        ' Options du compilateur
        cParam.CompilerOptions = "/t:library"  'L'assembly est une bibliothèque de classe,
        cParam.GenerateInMemory = True         'générée uniquement en mémoire.

        ' Génération du code source
        Dim sCode As System.Text.StringBuilder = New System.Text.StringBuilder("")
        sCode.AppendLine("Imports System")
        sCode.AppendLine("Imports System.Drawing")
        sCode.AppendLine("Imports System.Diagnostics")
        sCode.AppendLine()
        sCode.AppendLine("Namespace Divad")
        sCode.AppendLine(vbTab & "Class EvalVbCode")
        sCode.AppendLine(vbTab & vbTab & "Public Function EvalTransformation(ByVal img As Image) as Image")
        sCode.AppendLine(vbTab & vbTab & vbTab & "Try")
        sCode.AppendLine()
        sCode.AppendLine(cmd)
        sCode.AppendLine()
        sCode.AppendLine(vbTab & vbTab & vbTab & "Catch ex As Exception")
        ' En cas d'erreur : console de debug ET renvoie Nothing
        sCode.AppendLine(vbTab & vbTab & vbTab & vbTab & "Debug.WriteLine(ex.Message)")
        sCode.AppendLine(vbTab & vbTab & vbTab & vbTab & "Return Nothing")
        sCode.AppendLine(vbTab & vbTab & vbTab & "End Try")
        sCode.AppendLine(vbTab & vbTab & "End Function")
        sCode.AppendLine(vbTab & "End Class")
        sCode.AppendLine("End Namespace")
        ' Code de la classe dans la console de debug
        Debug.WriteLine(sCode.ToString())

        ' Résultat de la compilation
        Dim cResult As CodeDom.Compiler.CompilerResults = vbCodeProv.CompileAssemblyFromSource(cParam, sCode.ToString())
        If cResult.Errors.Count > 0 Then
            Dim Errors As String = "Erreur(s) : "
            For Each ce As CodeDom.Compiler.CompilerError In cResult.Errors
                Errors &= vbCrLf & ce.ErrorText
            Next ce
            MsgBox(Errors)
            Return Nothing
        Else
            ' Récupération de l'assembly généré
            Dim myAssembly As System.Reflection.Assembly = cResult.CompiledAssembly
            ' Instanciation de EvalVbCode
            Dim oEvalVbCode As Object = myAssembly.CreateInstance("Divad.EvalVbCode")
            ' Récupération du type de EvalVbCode
            Dim tEvalVbCode As Type = oEvalVbCode.GetType()
            ' Récupération de la méthode EvalTransformation
            Dim methodEvalTrans As Reflection.MethodInfo = tEvalVbCode.GetMethod("EvalTransformation")
            ' Invocation de la méthode EvalTransformation
            Dim myImage As Image = methodEvalTrans.Invoke(oEvalVbCode, New Object() {img})
            Return myImage
        End If
    End Function

Conclusion :


Cette technique, au final assez simple à mettre en place, peut être utilisée pour beacoup de choses... Je vous laisse faire courir votre imagination !

Vous trouverez une explication plus détaillée à cette adresse : http://www.laumaille.net/2007/12/19/evaluationexecution-dune-chaine/

Codes Sources

A voir également

Ajouter un commentaire Commentaires
Messages postés
94
Date d'inscription
lundi 13 janvier 2003
Statut
Membre
Dernière intervention
22 janvier 2009
2
Si je ne me trompe pas, il faut mettre Microsoft.VisualBasic.dll en référence, puis importer System.VisualBasic (ou System.VisualBasic.Interaction) pour avoir accès à la fonction MsgBox().
Mais il faut bien garder à l'esprit que cette fonction n'existe que pour garder une forme de compatibilité entre VB.Net et VB6, comme tout ce qui se trouve sous Microsoft.VisualBasic.
En .Net pur, il vaut mieux utiliser System.Windows.Forms.MessageBox.Show() (avec à peu près les même paramètres qu'en VB6).
De même, l'utilisation de modules est déconseillée en VB.Net, il vaut mieux créer une classe ! ;)

En espérant avoir pu t'aider !
Messages postés
22
Date d'inscription
vendredi 21 janvier 2005
Statut
Membre
Dernière intervention
3 janvier 2008

je cherchais justement a passer mon application de Vb6 en Visual 2005.
Voir le post : http://www.vbfrance.com/infomsg_SCRIPTCONTROL-VSA-CODEDOM_1054570.aspx

j'essaie de faire une programme qui pourrais dire :

Imports System
Module Script
Public Sub Main()
msgbox("hjkh")
msgbox(5*2)
End Sub
End Module

le gestionnaire de programme me dit que la ligne 5 et 6 ne sont pas declaré !!!

merci de votre aide
Messages postés
129
Date d'inscription
mardi 20 juillet 2004
Statut
Membre
Dernière intervention
6 juin 2009

C'est incroyable ce que ce morceau de code peut représenter ...
Il pourrait nous permettre de tester un morceau de code d'un programme, indépendament de la compilation de tout le reste dans un environnement vierge .. et dépourvu de bugs, afin d'en comprendre le fonctionnement et les erreurs évantuelles avant intégration au projet final ... Super ! 9/10
Messages postés
242
Date d'inscription
lundi 6 mars 2006
Statut
Membre
Dernière intervention
17 janvier 2018

oui tout à fait, c'est bien pour cela que je trouve ton exemple sympa et que je te met 8/10 :)

Ton code reprend MSDN et va un peu plus loin, mais c'est "dans les grandes lignes le même", c'est plutôt ça que j'aurais du dire.

Cordialement, KiTe.
Messages postés
94
Date d'inscription
lundi 13 janvier 2003
Statut
Membre
Dernière intervention
22 janvier 2009
2
Merci.

Il me semble quand même que le code est assez différent, mais de toute façon, j'utilise le même objet et ses propriétés ne changent pas !!
Et puis je pense surtout que cet exemple est plus "accessible", plus compréhensible pour un débutant que ce qui est donné sur la MSDN...
Afficher les 6 commentaires

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.