Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

C# Discussion :

Compilation de code à la volée


Sujet :

C#

  1. #1
    Membre habitué
    Compilation de code à la volée
    Bonjour,
    J'ai 2 questions pour le prix d'une.



    Environnement :
    • Windows 10
    • Visual Studio 2019 Community
    • Framework 4.8
    • C# 8


    A noter que le code est réduit à l'essentiel et que les chemins donnés sont réduits également.

    Ce que je fais :
    Je compile un code dynamiquement avec les outils System.CodeDom.Compiler.CodeDomProvider.CreateProvider() et System.CodeDom.Compiler.CompilerParameters().
    Pour cette compilation, je pointe des dll dont j'informe le compilateur de leur chemin d'accès (C:\MesDLLs\) qui est différent du répertoire courant de mon application (C:\MonAppli\bin\Debug\).
    Code C# :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    CompilerParameters parameters = new CompilerParameters();
     
    parameters.ReferencedAssemblies.AddRange(ReferencedAssemblies.ToArray());


    ReferencedAssemblies est de type List<string> pour avoir toutes les DLLs souhaitées.

    La compilation se passe bien, pas d'erreur, nickel

    Maintenant, je souhaite l'exécuter avec le code suivant :
    Code C# :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    // La compilation
    CompilerResults compil= CodeDomProvider.CreateProvider("csharp").CompileAssemblyFromSource(parameters, sourceCode);
     
    // La detection d'erreur
    if (compil.Errors.HasErrors)
    {
        foreach (CompilerError item in Errors)
            Console.WriteLine(($"Ligne {item.Line} : {item.ErrorNumber} <=> '{item.ErrorText}'{(item.Line > 0 ? $" => '{sourceCode.Split('\n')[item.Line - 1].Trim()}'" : string.Empty)}");
     
     
        throw new Exception($"Au moins une erreur de compilation est survenu pour '{className}'.");
    }
     
    // L'exécution
    compil.CompiledAssembly.GetType("MonType").GetMethod("MaMethode").Invoke(obj, parameters);

    Et là ça crache, avec le message d'erreur suivant :

    Message d'erreur => Une exception a été levée par la cible d'un appel.

    Message d'erreur dans le InnerException => Impossible de charger le fichier ou l'assembly 'MaDLL, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null' ou une de ses dépendances. Le fichier spécifié est introuvable.

    Et particularité de System.Reflexion.TargetInvolationException, j'ai une propriété FusionLog qui me donne tout ça =>
    === Informations d'état de liaison préalable ===
    JRN*: DisplayName = MaDLL, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null
    (Fully-specified)
    JRN*: Appbase = file:///C:/MonAppli/bin/Debug/
    JRN*: PrivatePath initial = NULL
    Assembly appelant*: (Unknown).
    ===
    JRN*: cette liaison démarre dans le contexte de chargement de default.
    JRN*: utilisation du fichier de configuration de l'application*: C:\MonAppli\bin\Debug\MonAppli.exe.Config
    JRN*: utilisation du fichier de configuration d'hôte*:
    JRN*: utilisation du fichier de configuration de l'ordinateur à partir de C:\Windows\Microsoft.NET\Framework\v4.0.30319\config\machine.config.
    JRN*: stratégie non appliquée à la référence à ce stade (liaison d'assembly privée, personnalisée, partielle ou basée sur l'emplacement).
    JRN*: tentative de téléchargement de la nouvelle URL file:///C:/MonAppli/bin/Debug/MaDLL.DLL.
    JRN*: tentative de téléchargement de la nouvelle URL file:///C:/MonAppli/bin/Debug/MaDLL/MaDLL.DLL.
    JRN*: tentative de téléchargement de la nouvelle URL file:///C:/MonAppli/bin/Debug/MaDLL.EXE.
    JRN*: tentative de téléchargement de la nouvelle URL file:///C:/MonAppli/bin/Debug/MaDLL/MaDLL.EXE.
    (Bien sûr, MonType et MaMethode n'ont pas d'erreur de frappe et existe bien dans le code fraîchement compilé)

    Première question :
    Pourquoi la compilation OK mais pas l'exécution ?



    Après quelques heures (jours) à chercher, je teste ceci :
    Je copie manuellement mes DLLs dans le répertoire C:/MonAppli/bin/Debug/ => Et là ça fonctionne

    Je peux aussi ajouter une référence à ces DLLs depuis mon projet MonAppli mais cela ne me convient pas car ce sont des DLLs également compilées à la volée au début de l'exécution du programme et je ne les connais pas à l'avance (officiellement).

    Première question subsidiaire :
    Comment dire à mon projet d'aller voir également le répertoire C:\MesDLLS\ ?
    J'ai essayé en ajoutant le chemin dans les chemins d'accès des références dans la fenêtre des propriétés du projet, cela n'a pas fonctionné
    J'ai essayé en l'ajoutant au PATH système de windows pour l'ajouter, cela n'a pas fonctionné non plus...

    Seconde question :
    Dans le code, j'ai
    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    int a = 1; Console.WriteLine(a.ToString("00"))

    Que j'ai transformé en
    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    int a = 1; Console.WriteLine($"{a:00}"))


    Et là, à la compilation, j'ai cette erreur :
    Ligne 12 : CS1056 <=> 'Caractère '$' inattendu' => 'int a = 1; Console.WriteLine($"{a:00}");'
    Je n'ai pas envie de revenir au .ToString("00"), on se fait vite au sucre syntaxique... Et surtout, il y en a partout... Comment résoudre ce problème ?

    Voilà, merci d'avoir lu mes questions, et encore plus d'y répondre ou de donner des pistes de recherche pour y répondre.

  2. #2
    Membre expert
    Bonjour,

    Pour ta première question, lors de l'exécution d'une assembly primaire (.exe) la recherche des références s'effectue dans des répertoires spécifiques comme tu auras pu le remarquer une référence côte à côte est de suite trouvée.
    Si tu veux cibler un autre répertoire de recherche (ex : C:\) il faut le prévoir dans ton binaire grâce à l’événement "ResolveEventHandler". Exemple ici :
    https://stackoverflow.com/questions/...runtime-in-net

    Bon codage++

  3. #3
    Membre habitué
    Super, reste la seconde question...
    Salut Wallace1,
    Merci pour ta réponse, elle donne effectivement une bonne piste et après avoir bidouillé un petit quelque chose avec au niveau de mon projet, ça fonctionne.

    Maintenant je vais voir si là où je l'ai mis est le plus pertinent ou s'il aurait plus sa place ailleurs (ça dépend surtout de la structure de ma solution donc je ne rentre pas dans les détail ici).

    Reste la seconde question à propos du sucre syntaxique, des idées à propos de ce $ ?

  4. #4
    Membre habitué
    Ce n'est pas dans la question initiale mais...
    Je continue mes tests et je découvre un problème similaire à ma question 2 à propos du $...

    Lorsque j'écris le code suivant :
    Code C# :Sélectionner tout -Visualiser dans une fenêtre à part
    var a = MonObjet?.MaPropriete;
    , contraction de
    Code C# :Sélectionner tout -Visualiser dans une fenêtre à part
    var a = null; if (MonObjet != null) a = MonObjet.MaPropriete;

    J'ai 3 erreurs d'un coup :
    Ligne 25 : CS1525 <=> 'Terme d'expression non valide '.'' => 'var a = MonObjet?.MaPropriete;'
    Ligne 25 : CS1003 <=> 'Erreur de syntaxe, ':' attendu' => 'var a = MonObjet?.MaPropriete;'
    Ligne 25 : CS1002 <=> '; attendu' => 'var a = MonObjet?.MaPropriete;'
    Des idées ?

  5. #5
    Membre expert
    RE, je n'ai pas eu le temps de répondre à ta 2ème question tout à l'heure.....

    Je ne sais pas si codedom prends vraiment en compte ce type de raccourci syntaxique mais j'ai tout de même une question :

    As-tu essayés de déclarer la version de ton cscodeprovider (lié à la version du Framework) ?

    Exemple très succint :

    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    var Version = new Dictionary<string, string>() { { "CompilerVersion", "4.8"} };
    CSCodeProvider cProv = new CSCodeProvider(Version);
    CompilerParameters cParams = new CompilerParameters();
    ....
    ........


    ++

  6. #6
    Membre habitué
    Je pense surtout que c'est lié à la version du language c# qui n'est plus piloté par la version du Framework à présent.
    de mémoire il faut s'appuyer sur le package Microsoft.CodeDom.Providers.DotnetCompilerPlatform pour parvenir à compiler une version plus récente du C# via CSCodeProvider.
    Mon blog est sur https://arphonis.fr et bientôt d'autres fonctionnalités seront disponible dessus.

  7. #7
    Membre habitué
    @wallace1 : Cela ne fonctionne guère mieux, je dirais même plus : ca fonctionne moins bien car il me répond que "Le fichier exécutable du compilateur csc.exe est introuvable." à la compilation à la volée...
    @estacodo : J'ai du mal à comprendre comment utiliser ce nuget package, d'autant plus que je ne fais pas de dev ASP.Net.

    Après installation du nugut package, à la compilation de mon code, j'ai
    System.InvalidOperationException : Le fichier exécutable du compilateur csc.exe est introuvable.
    Après recherche, j'ai trouvé le package Microsoft.CodeDom.Providers.DotnetCompilerPlatform.BinFix spécialement pour les projet non ASP.Net et là, c'est à la compilation de mon projet que ça ne passe pas :
    CS1617 Invalid option 'preview' for /langversion; must be ISO-1, ISO-2, Default or an integer in range 1 to 6.
    En même temps, le package date de février 2016 !!! 7 et 8 sont certainement arrivé après...


    Il doit y avoir visual studio qui fait une précompilation...

  8. #8
    Expert confirmé
    Citation Envoyé par ypelissier Voir le message
    Je continue mes tests et je découvre un problème similaire à ma question 2 à propos du $...

    Lorsque j'écris le code suivant :
    Code C# :Sélectionner tout -Visualiser dans une fenêtre à part
    var a = MonObjet?.MaPropriete;
    , contraction de
    Code C# :Sélectionner tout -Visualiser dans une fenêtre à part
    var a = null; if (MonObjet != null) a = MonObjet.MaPropriete;

    J'ai 3 erreurs d'un coup :


    Des idées ?
    Pour la version de System.CodeDom plus récente il y a celle -là à voir :
    System.CodeDom version="4.7.0" targetFramework="net461" de nov.2019
    la même revue mais à des dates postérieure à nov.2019 .

    Sous forme de package nuget sur ce lien:
    https://www.nuget.org/packages/System.CodeDom/


    Quant à l'operateur ternaire ? c'est du "syntaxic sugar" et dans le CodeDom sa construction syntaxique de base est simplement un "if/else".
    bon code.

  9. #9
    Membre habitué
    Bonjour,
    @MABROUKI : A la base, avant de télécharger le nuget package dont tu me parles, quand j'utilise CodeDomProvider, Visual Studio me suggère d'utiliser using System.CodeDom.Compiler;.
    Lorsque je vais voir la référence de CodeDomProvider, je peux voir que System.CodeDom.Compiler se trouve dans la DLL System.dll
    Code C# :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    #region assembly System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
    // C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.8\System.dll
    #endregion


    Après l'avoir référencé (le nuget package), lorsque je fais la même opération, en ayant pris soin de retirer le using, VS ne me propose pas d'autres alternatives que de me faire pointer sur System.CodeDom.Compiler . Comment pointer sur le package nouvellement référencé ?

    @Tous :
    J'ai fait un micro-projet pour pouvoir le tester :
    Code C# :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    using System;
    using System.CodeDom.Compiler;
     
    namespace CompilationALaVolee
    {
        class Program
        {
            static void Main(string[] args)
            {
                var sourceCode = "using System;\r\n" +
                "namespace TestNamespace\r\n" +
                "{\r\n" +
                    "\tpublic static class TestClass\r\n" +
                    "\t{\r\n" +
                        "\t\tpublic static void TestMethod()\r\n" +
                        "\t\t{\r\n" +
                            "\t\t\tint? i = 5;\r\n" +
                            "\t\t\tConsole.WriteLine($\"Test {i}\");\r\n" + // Pour tester le $""
                            //"\t\t\tConsole.WriteLine(\"Test \" + i?.ToString());\r\n" + // Pour tester le ?.
                        "\t\t}\r\n" +
                    "\t}\r\n" +
                "}\r\n";
     
                CompilerParameters parameters = new CompilerParameters();
     
                parameters.ReferencedAssemblies.Add("System.dll");
                parameters.OutputAssembly = "Test.dll";
                parameters.CompilerOptions = "/t:library";
                parameters.GenerateInMemory = false;
                parameters.GenerateExecutable = false;
                parameters.IncludeDebugInformation = false;
     
                var results = CodeDomProvider.CreateProvider("csharp"
                                                            //, new Dictionary<string, string> { { "CompilerVersion", "4.8"} } // Si ligne présente alors => System.InvalidOperationException*: 'Le fichier exécutable du compilateur csc.exe est introuvable.'
                                                            ).CompileAssemblyFromSource(parameters, sourceCode);
     
                if (results.Errors.HasErrors)
                    foreach (CompilerError item in results.Errors)
                        Console.WriteLine(item.ErrorNumber + " <=> " + item.ErrorText);
                else
                    results.CompiledAssembly.GetType("TestNamespace.TestClass")
                                            .GetMethod("TestMethod")
                                            .Invoke(null, null);
     
                Console.ReadLine();
            }
        }
    }


    Si installation de Microsoft.CodeDom.Providers.DotNetCompilerPlatform => // System.InvalidOperationException*: 'Le fichier exécutable du compilateur csc.exe est introuvable.', comme pour l'indication de la version du compilateur
    Si installation de Microsoft.CodeDom.Providers.DotNetCompilerPlatform.BinFix => CS1617 Invalid option 'preview' for /langversion; must be ISO-1, ISO-2, Default or an integer in range 1 to 6.

    Contenu du fichier Directory.Build.props
    Code XML :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    <Project>
     <PropertyGroup>
       <LangVersion>preview</LangVersion>
     </PropertyGroup>
    </Project>


    Si changement de version pour la 6 (pas souhaité, je veux bien redescendre en 8.0 mais pas en 6), retour au point de départ => CS1056 <=> Caractère '$' inattendu...

    J'ai comme qui dirait l'impression de tourner en rond...

    Quelqu'un aurait-il une autre proposition ou un élément complémentaire à me proposer ?

    Merci beaucoup

  10. #10
    Expert confirmé
    Citation Envoyé par ypelissier Voir le message


    Si installation de Microsoft.CodeDom.Providers.DotNetCompilerPlatform => // System.InvalidOperationException*: 'Le fichier exécutable du compilateur csc.exe est introuvable.', comme pour l'indication de la version du compilateur
    Si installation de Microsoft.CodeDom.Providers.DotNetCompilerPlatform.BinFix => CS1617 Invalid option 'preview' for /langversion; must be ISO-1, ISO-2, Default or an integer in range 1 to 6.

    Contenu du fichier Directory.Build.props
    Code XML :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    <Project>
     <PropertyGroup>
       <LangVersion>preview</LangVersion>
     </PropertyGroup>
    </Project>


    Si changement de version pour la 6 (pas souhaité, je veux bien redescendre en 8.0 mais pas en 6), retour au point de départ => CS1056 <=> Caractère '$' inattendu...

    J'ai comme qui dirait l'impression de tourner en rond...

    Quelqu'un aurait-il une autre proposition ou un élément complémentaire à me proposer ?

    Merci beaucoup
    Mai non,non !!!
    En ce qui concerne le message énigmatique 'Le fichier exécutable du compilateur csc.exe est introuvable" c'est un bogue dans cette Api.
    Le chemin du compilateur Roslyn (aka csc.exe ou "roseline") ,est code en dur c.à.d. dire :
    Si ton appli de bureau est compilée dans \TonProjet\debug\bin\exemple.exe,
    le compilateur roslyn sera situé dans
    -\TonProjet\debug\bin\roslyn\csc.exe(voir dossier debug de ton projet),
    Mais le CSharpCodeProvider RESOUDRA(recherchera) csc.exe comme étant dans:
    \TonProjet\debug\bin\csc.exe.

    En raison de ce problème et de la nécessité d'appeler un programme externe pour faire
    ce qui doit être fait en cours de processus, cette API est dite "broken" ou complètement cassée.
    Le programme externe en cause c'est les lignes de code suivantes à rajouter:
    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
       //-------------------------------------------------
        //Set hardcoded environment variable to set the path to the library
        Environment.SetEnvironmentVariable("ROSLYN_COMPILER_LOCATION", "actual ROSLYN compiler location goes here", EnvironmentVariableTarget.Process);
        //Create compiler object
        CSharpCodeProvider compiler = new CSharpCodeProvider();
        //Clean up
        Environment.SetEnvironmentVariable("ROSLYN_COMPILER_LOCATION", null, EnvironmentVariableTarget.Process);


    Compilé dans vs 2017 .net framework version 4.7 l'exemple de code suivant compile et s'execute perfectly:

    1/ class CodeDomExample
    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
     
     
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.IO;
    using System.CodeDom;
    using System.CodeDom.Compiler;
    using Microsoft.CodeDom.Providers.DotNetCompilerPlatform;
     
    namespace WinDotNetCompilers
    {
        class CodeDomExample
        {
     
            public static CodeCompileUnit BuildHelloWorldGraph()
            { 
                //' Create a new CodeCompileUnit to contain 
                //' the program graph.
                CodeCompileUnit compileUnit =
                    new CodeCompileUnit();
     
                //' Declare a new namespace called Samples.
                CodeNamespace samples = 
                    new CodeNamespace("Samples");
     
                //' Add the new namespace .
                compileUnit.Namespaces.Add(samples);
     
                // Add  import for the System 
                samples.Imports.Add(new CodeNamespaceImport("System"));
     
                // Declare a new type .
                CodeTypeDeclaration class1 =
                        new CodeTypeDeclaration("Class1");
     
                //' Add the new type to the namespace type collection.
                samples.Types.Add(class1);
                CodeTypeParameter parm = new CodeTypeParameter();
     
                CodeMemberField fieldInt = new CodeMemberField();
                fieldInt.Name="num";
                fieldInt.Type = new CodeTypeReference("System.Nullable<Int32>");
                fieldInt.Attributes =MemberAttributes.Private;
                class1.Members.Add(fieldInt);
     
                CodeMemberProperty property1 = new CodeMemberProperty();
                property1.Name = "Num";
                property1.Type = new CodeTypeReference("System.Nullable<Int32>");
                property1.Attributes = MemberAttributes.Final;
     
                property1.GetStatements.Add( new CodeMethodReturnStatement(
                    new CodeFieldReferenceExpression(
                        new CodeThisReferenceExpression(), fieldInt.Name)));
                property1.SetStatements.Add( new CodeAssignStatement( 
                    new CodeFieldReferenceExpression(
                        new CodeThisReferenceExpression(), fieldInt.Name), 
                        new CodePropertySetValueReferenceExpression()));
                class1.Members.Add(property1);
     
                // ici à toi d'ajouter le class Program(codeentrypoint)
                // qui teste ce class
     
                return compileUnit;
            }
            public static void GenerateCode(CodeDomProvider provider, CodeCompileUnit compileunit )
            {   
                //  Build the source file name with the appropriate
                // language extension.
                string sourceFile ;
                if  ( provider.FileExtension.StartsWith(".") )
                    sourceFile = "TestGraph" + provider.FileExtension;
                else
                    sourceFile = "TestGraph." + provider.FileExtension;
     
     
                    // Create an IndentedTextWriter, constructed with
                    // a StreamWriter to the source file.
                    IndentedTextWriter tw = new IndentedTextWriter(
                       new StreamWriter(sourceFile, false), "    ");
                    // Generate source code using the code generator.
                    provider.GenerateCodeFromCompileUnit(compileunit, tw, new CodeGeneratorOptions());
                    // Close the output file.
                    tw.Close();
            }
            public static CompilerResults CompileCode( CodeDomProvider provider, 
                                           string sourceFile,string exeFile)
            {
                    //Configure a CompilerParameters that links System.dll
                    //and produces the specified executable file.
                    string[] referenceAssemblies  = {"System.dll"};
                    CompilerParameters cp =new CompilerParameters(referenceAssemblies, exeFile, false);
     
                    //Generate an executable rather than a DLL file.
                    cp.GenerateExecutable = true;
     
                    //Invoke compilation.
                    CompilerResults cr  = 
                        provider.CompileAssemblyFromFile(cp,sourceFile);
                    //Return the results of compilation.
                    return cr;
            }
        }
    }


    2/ form user de test:
    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
     
    using System;
    using System.CodeDom.Compiler;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Diagnostics;
    using System.Drawing;
    using System.IO;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    using System.Windows.Forms;
    using Microsoft.CodeDom.Providers.DotNetCompilerPlatform;
    namespace WinDotNetCompilers
    {
        public partial class Form1 : Form
        {
            public Form1()
            {
                InitializeComponent();
            }
     
            private void generate_button_Click(object sender, EventArgs e)
            {
                //Create CodeDomProvider
                //Set hardcoded environment variable to set the path to the library
                Environment.SetEnvironmentVariable("ROSLYN_COMPILER_LOCATION", @"C:\Users\ypelissier\Desktop\WinDotNetCompilers\bin\Debug\roslyn", EnvironmentVariableTarget.Process);
                CSharpCodeProvider provider = new CSharpCodeProvider();
                //Clean up
                Environment.SetEnvironmentVariable("ROSLYN_COMPILER_LOCATION", null, EnvironmentVariableTarget.Process);
     
     
                CodeDomExample.GenerateCode(provider, CodeDomExample.BuildHelloWorldGraph());
     
                // Build the source file name with the appropriate
                // language extension.
                string sourceFile = string.Empty;
                if (provider.FileExtension.StartsWith("."))
                    sourceFile = "TestGraph" + provider.FileExtension;
                else
                    sourceFile = "TestGraph." + provider.FileExtension;
     
     
                //' Read in the generated source file and
                //' display the source text.
                StreamReader sr = new StreamReader(sourceFile);
                textBox1.Text = sr.ReadToEnd();
                sr.Close();
            }
     
            private void compile_button_Click(object sender, EventArgs e)
            {
                //Create CodeDomProvider
     
                //Set hardcoded environment variable to set the path to the library
                  Environment.SetEnvironmentVariable("ROSLYN_COMPILER_LOCATION", @"C:\Users\ypelissier\Desktop\WinDotNetCompilers\bin\Debug\roslyn", EnvironmentVariableTarget.Process);
     
                CSharpCodeProvider provider = new CSharpCodeProvider();
                //Clean up
                Environment.SetEnvironmentVariable("ROSLYN_COMPILER_LOCATION", null, EnvironmentVariableTarget.Process);
     
     
                string sourceFile = string.Empty;
                if (provider.FileExtension.StartsWith("."))
                    sourceFile = "TestGraph" + provider.FileExtension;
                else
                    sourceFile = "TestGraph." + provider.FileExtension;
     
                CompilerResults cr =
                    CodeDomExample.CompileCode(provider, sourceFile, "TestGraph.EXE");
     
                if (cr.Errors.Count > 0)
                {
                    //Display compilation errors.
                    textBox1.Text =
                        "Errors encountered while building " +
                                sourceFile + " into " +
                                cr.PathToAssembly + ": " + Environment.NewLine;
     
     
                    foreach (CompilerError ce in cr.Errors)
                    {
                        textBox1.AppendText(ce.ToString() + Environment.NewLine);
                    }
                    run_button.Enabled = false;
                }
                else
                {
                    textBox1.Text = "Source " + sourceFile + " built into " +
                                    cr.PathToAssembly + " with no errors.";
                    run_button.Enabled = true;
                }
            }
     
            private void run_button_Click(object sender, EventArgs e)
            {
                Process.Start("TestGraph.EXE");
            }
     
     
         }
    }

    Ton code devrait compiler et s'exécuter correctement .
    bon code....

###raw>template_hook.ano_emploi###