none
Créer un langage ressemblant au c# pour coder pour coder dans un autre programme RRS feed

  • Question

  • Bonjour,

    Dans une application que j'ai créée, il faut que j'invente un langage me permettant de faire des scripts qui pourront être décodés pour s'exécuter dans la même application, mais d'un autre utilisateur. J'aimerais qu'il réutilise la syntaxe de C# et les mêmes variables de base (string, char, int, bool, float, double...). De plus, il serait intéressant qu'il puisse aussi utiliser certaines dlls du .NET Framework. Selon ce que j'en ai déduit, l'utilisateur écrira son code qui sera compilé et ensuite collé dans un fichier texte. Lors du décodage, l'application lira le fichier et va créer toutes les fonctions, les classes, les variables et tout le reste pour ensuite exécuter la fonction <<Main>> de celui-ci.

        Mon problème est que je ne sais pas par où commencer et comment m'y prendre. Quelqu'un aurait-il un tutoriel ou la réponse tout simplement? :)

    lundi 12 juillet 2010 19:44

Réponses

  • Bonjour,

    Dans ce cas le langage C# serait plus judicieux :

    Dans votre cas, il suffit d'utiliser la classe CodeDomProvider pour récupérer le compilateur C#. Avec ce compilateur, vous compilez un Assembly, auquel il faudra parcourir les classes par introspection, afin d'y trouver une méthode static Main().

    Voici un exemple :

    CodeDomProvider p;
    CompilerResults result;
    string codeUtilisateur;
    
    codeUtilisateur = "using System;" +
      "public class ClasseUtilisateur {" +
      " public static void Main() {" +
      "  Console.WriteLine(\"Bonjour !!\"); }" +
      " } ";
    
    p = CodeDomProvider.CreateProvider("C#");
    result = p.CompileAssemblyFromSource(new CompilerParameters(), new string[] { codeUtilisateur });
    
    if (result.Errors.Count > 0)
    {
      // Insulter l'utilisateur... :-)
    }
    else
    {
      // Rechercher toutes les classes contenant une méthode static Main()
    
      MethodInfo[] m;
    
      m = result.CompiledAssembly.GetTypes()
          .SelectMany(classe => classe.GetMethods())
          .Where(méthode => méthode.Name == "Main")
          .Where(méthode => (méthode.Attributes & MethodAttributes.Static) == MethodAttributes.Static)
          .ToArray();
    
      if (m.Length == 1)
      {
        // Appeler la méthode
        m[0].Invoke(null, new object[0]);
      }
      else
      {
        // Insulter l'utilisateur car plusieurs méthodes Main()
      }
    }
    

    Cordialement


    Gilles TOURREAU - MVP C# - MCTS Windows Forms - Architecte .NET/Consultant/Formateur - http://gilles.tourreau.fr
    • Marqué comme réponse Alex Petrescu vendredi 16 juillet 2010 08:30
    mercredi 14 juillet 2010 10:08
    Modérateur
  • Bonjour,

    méthode.Attributes peut prendre plusieurs valeurs (c'est une énumération avec FlagsAttribute). Par exemple MethodAttributes.Static et MethodAttributes.Public pour une méthode public et static.

    On utilise donc l'opérateur ET binaire (&) afin de récupérer la valeur qui nous conviennent.

    Est-ce que cela éclair votre lanterne ?

    Cordialement


    Gilles TOURREAU - MVP C# - MCTS ADO .NET 3.5 - MCPD Windows Developper 3.5 - Architecte .NET/Consultant/Formateur - http://gilles.tourreau.fr
    mardi 17 août 2010 20:45
    Modérateur

Toutes les réponses

  • Bonjour,

    Pourquoi ne pas intégrer PowerShell dans votre application ?

    Cordialement


    Gilles TOURREAU - MVP C# - MCTS Windows Forms - Architecte .NET/Consultant/Formateur - http://gilles.tourreau.fr
    lundi 12 juillet 2010 20:53
    Modérateur
  • Bonjour, J'ai demandé à mon ami google quelques informations sur PowerShell et, de ce que j'ai lu, je ne vois pas comment il pourrait m'être utile. Voici la meilleure définition que j'ai trouvé: <<PowerShell est un environnement interactif. On peut s'en servir en tant que remplacement de CMD.EXE pour naviguer dans les fichiers, parcourir le réseau, vérifier et/ou modifier tel ou tel élément de configuration (local ou distant) grâce à WMI, .NET ou COM. Le tout peut être fait en avançant pas à pas, en essayant une commande et en la peaufinant grâce à un retour immédiat.>> Source: http://groupes.codes-sources.com/article-powershell-csharp-82377.aspx Quelle est votre définition de PowerShell?
    mardi 13 juillet 2010 00:46
  • Bonjour,

    Ma définition : PowerShell permet d'executer interactivement (et donc scripter) du code .NET. Vos utilisateurs peuvent créer un script PowerShell qui utilise des objets .NET (de votre application). Ces scripts peuvent-être bien évidemment executé dans votre application.

    J'ai offert à mes clients avancés, un fournisseur PowerShell permettant de parcourir leur SI. Par exemple voici comment imprimer massivement toutes les factures de 2010 :

    cd SI:\Factures
    dir FA2010* | ForEach-Object {$_.Imprimer()}

    Quand vous faites "dir FA2010*" au lieu de retourner des objets FileInfo, ce sont des objets métiers Facture qui sont retournés.

    Bien évidemment cet exemple est en ligne de commande, mais l'utilisateur peut facilement scripter le tout à sa guise...

    Cordialement


    Gilles TOURREAU - MVP C# - MCTS Windows Forms - Architecte .NET/Consultant/Formateur - http://gilles.tourreau.fr

    mardi 13 juillet 2010 04:12
    Modérateur
  • Donc, il faudra apprendre un nouveau langage de codage? Si l'on ne peut pas coder juste en C#, auriez-vous de bons tutoriels? Sommes-nous obligés de télécharger PowerShell pour scripter et exécuter ou juste copier coller les bibliothèques est correcte?
    mardi 13 juillet 2010 12:21
  • Bonjour,

    Donc, il faudra apprendre un nouveau langage de codage?
    Oui, vous voulez que l'utilisateur utilise C# ? Quel type d'utilisateur va utiliser votre langage ? A quoi pourrait servir C# ou PowerShell dans votre application ?

    Si l'on ne peut pas coder juste en C#, auriez-vous de bons tutoriels
    A la sortie de PowerShell, j'ai lu la documentation de démarrage Microsoft qui permet de découvrir et apprendre C# facilement.

    Sommes-nous obligés de télécharger PowerShell pour scripter et exécuter ou juste copier coller les bibliothèques est correcte?
    Il me semble que non... Mais à vérifier. 

    Cordialement


    Gilles TOURREAU - MVP C# - MCTS Windows Forms - Architecte .NET/Consultant/Formateur - http://gilles.tourreau.fr
    mardi 13 juillet 2010 12:31
    Modérateur
  • Bonjour,

    Oui, vous voulez que l'utilisateur utilise C# ?

    Oui, car je le trouve très simple à apprendre (du moins la base)

     

    Quel type d'utilisateur va utiliser votre langage ?

    N'importe quel ayant téléchargé mon application.

     

    A quoi pourrait servir C# ou PowerShell dans votre application ?

    Pour tout expliquer, je crée un jeux en C# avec son éditeur de cartes. J'aimerais que l'éditeur soit puissant en ajoutant un langage script facile à utiliser et très ressemblant au C# qui permettrait de faire des déclencheurs ayant un nombre illimité d'évennement, de conditions et d'actions.

     

    Merci pour vos réponses.

    mardi 13 juillet 2010 17:22
  • Bonjour,

    Dans ce cas le langage C# serait plus judicieux :

    Dans votre cas, il suffit d'utiliser la classe CodeDomProvider pour récupérer le compilateur C#. Avec ce compilateur, vous compilez un Assembly, auquel il faudra parcourir les classes par introspection, afin d'y trouver une méthode static Main().

    Voici un exemple :

    CodeDomProvider p;
    CompilerResults result;
    string codeUtilisateur;
    
    codeUtilisateur = "using System;" +
      "public class ClasseUtilisateur {" +
      " public static void Main() {" +
      "  Console.WriteLine(\"Bonjour !!\"); }" +
      " } ";
    
    p = CodeDomProvider.CreateProvider("C#");
    result = p.CompileAssemblyFromSource(new CompilerParameters(), new string[] { codeUtilisateur });
    
    if (result.Errors.Count > 0)
    {
      // Insulter l'utilisateur... :-)
    }
    else
    {
      // Rechercher toutes les classes contenant une méthode static Main()
    
      MethodInfo[] m;
    
      m = result.CompiledAssembly.GetTypes()
          .SelectMany(classe => classe.GetMethods())
          .Where(méthode => méthode.Name == "Main")
          .Where(méthode => (méthode.Attributes & MethodAttributes.Static) == MethodAttributes.Static)
          .ToArray();
    
      if (m.Length == 1)
      {
        // Appeler la méthode
        m[0].Invoke(null, new object[0]);
      }
      else
      {
        // Insulter l'utilisateur car plusieurs méthodes Main()
      }
    }
    

    Cordialement


    Gilles TOURREAU - MVP C# - MCTS Windows Forms - Architecte .NET/Consultant/Formateur - http://gilles.tourreau.fr
    • Marqué comme réponse Alex Petrescu vendredi 16 juillet 2010 08:30
    mercredi 14 juillet 2010 10:08
    Modérateur
  • Merci, je vais essayer d'en apprendre plus sur la classe CodeDomProvider. :)

    vendredi 16 juillet 2010 12:14
  • Bonjour,

    Maintenant que j'en connais un peu plus sur le CodeDomProvider, je voudrais savoir pourquoi vous avez marqué:

    .Where(méthode => (méthode.Attributes & MethodAttributes.Static) == MethodAttributes.Static)

    et non: .Where(méthode => méthode.Attributes   == MethodAttributes.Static)?

    Cordialement

    mardi 17 août 2010 18:25
  • Bonjour,

    méthode.Attributes peut prendre plusieurs valeurs (c'est une énumération avec FlagsAttribute). Par exemple MethodAttributes.Static et MethodAttributes.Public pour une méthode public et static.

    On utilise donc l'opérateur ET binaire (&) afin de récupérer la valeur qui nous conviennent.

    Est-ce que cela éclair votre lanterne ?

    Cordialement


    Gilles TOURREAU - MVP C# - MCTS ADO .NET 3.5 - MCPD Windows Developper 3.5 - Architecte .NET/Consultant/Formateur - http://gilles.tourreau.fr
    mardi 17 août 2010 20:45
    Modérateur
  • Ah ok merci :)
    mercredi 18 août 2010 13:32