Exemplo n.º 1
0
        /// Produce solution files
        private static void beautifyOutput(bool prov35, CompiledOutputType outputtype, CompileOptions options, CompilerParameters param, Dictionary<string, string> resources, string moduleName, Version neededVersion)
        {
            string id = Path.GetFileNameWithoutExtension(moduleName);
            string tempName = null;
            string projName = null;
            string cs=null;

            foreach (string t in param.TempFiles)
            {
                if (!File.Exists(t))
                    continue;

                if (tempName == null)
                    tempName = Path.GetFileNameWithoutExtension(t);
                string ext = Path.GetExtension(t).ToLower().TrimStart('.');
                string newName = Path.Combine(Path.GetDirectoryName(t), id + "." + ext);
                File.Delete(newName);
                if (ext == "cs")
                {

                    File.Move(t, newName);
                    cs = newName;
                }

                if (ext == "cmdline")
                {
                    string s = File.ReadAllText(t);

                    string csc = "csc.exe";
                    // Get compiler path
                    foreach (Version v in Utils.GetInstalledNETVersions())
                    {
                        if (neededVersion > v)
                            continue;
                        DirectoryInfo d = Utils.FindNETFrameworkDirectory(v);
                        if (d == null)
                            continue;
                        string fn = Path.Combine(d.FullName, "csc.exe");
                        if (File.Exists(fn))
                        {
                            csc = Utils.QuoteArg(fn);
                            break;
                        }
                    }

                    s = csc + " /noconfig " + s;
                    s = s.Replace(tempName + ".0", id);
                    s = s.Replace(tempName, id);

                    newName = Path.Combine(Path.GetDirectoryName(t), "compile_" + id + ".bat");
                    projName= Path.Combine(Path.GetDirectoryName(t), id + ".csproj");
                    File.Delete(newName);
                    File.WriteAllText(newName, s);
                }
                File.Delete(t);
            }

            // Write project file
            if (projName!=null )
            {
                Guid projGuid = Guid.NewGuid();
                string dir = Path.GetFullPath(Path.GetDirectoryName(projName));
                using (XmlWriter x = XmlWriter.Create(projName,new XmlWriterSettings() { Indent = true, IndentChars = "  "}))
                {
                    string ns = "http://schemas.microsoft.com/developer/msbuild/2003";
                    x.WriteStartElement("Project",ns);
                    if (prov35)
                        x.WriteAttributeString("ToolsVersion", (Environment.Version.Major>=4)?"4.0.30319": "3.5");
                    x.WriteAttributeString("DefaultTargets", "Build");

                    x.WriteStartElement("PropertyGroup", ns);
                    x.WriteStartElement("Configuration");x.WriteAttributeString("Condition"," '$(Configuration)' == '' ");x.WriteValue("Debug");x.WriteEndElement();
                    x.WriteStartElement("Platform"); x.WriteAttributeString("Condition", " '$(Platform)' == '' "); x.WriteValue("AnyCPU"); x.WriteEndElement();
                    x.WriteElementString("ProductVersion","9.0.30729");
                    x.WriteElementString("SchemaVersion","2.0");
                    x.WriteElementString("ProjectGuid", projGuid.ToString("B").ToUpper());

                    if (outputtype == CompiledOutputType.Library)
                        x.WriteElementString("OutputType", "Library");
                    else if (outputtype == CompiledOutputType.WindowsExe)
                        x.WriteElementString("OutputType", "WinExe");
                    else
                        x.WriteElementString("OutputType", "Exe");
                    x.WriteElementString("AssemblyName", Path.GetFileNameWithoutExtension(projName));
                    x.WriteElementString("ErrorReport", "prompt");
                    x.WriteElementString("WarningLevel", "4");
                    if (prov35)
                    {
                        if (options.Icon != null)
                            x.WriteElementString("ApplicationIcon", str_icon);
                        if (options.Manifest != null)
                            x.WriteElementString("ApplicationManifest", str_manifest);
                    }
                    else
                        x.WriteElementString("Win32Resource", str_w32resources);

                    x.WriteEndElement(); // Property group

                    x.WriteStartElement("PropertyGroup", ns);
                    x.WriteAttributeString("Condition", " '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ");
                    x.WriteElementString("DebugType", "Full");
                    x.WriteElementString("DebugSymbols", "true");
                    x.WriteElementString("OutputPath", "bin\\Debug\\");
                    x.WriteElementString("DefineConstants", "DEBUG;TRACE;");
                    x.WriteElementString("Optimize", "false");
                    x.WriteEndElement(); // Property group

                    x.WriteStartElement("PropertyGroup", ns);
                    x.WriteAttributeString("Condition", " '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ");
                    x.WriteElementString("DebugType", "pdbonly");
                    x.WriteElementString("DebugSymbols", "false");
                    x.WriteElementString("OutputPath", "bin\\Release\\");
                    x.WriteElementString("DefineConstants", "TRACE;");
                    x.WriteElementString("Optimize", "true");
                    x.WriteEndElement(); // Property group

                    x.WriteStartElement("Import", ns);
                    x.WriteAttributeString("Project","$(MSBuildToolsPath)\\Microsoft.CSharp.targets");
                    x.WriteEndElement(); // Import

                    x.WriteStartElement("ItemGroup", ns);
                    foreach (var r in resources)
                    {
                        x.WriteStartElement("EmbeddedResource", ns);
                        x.WriteAttributeString("Include", root(dir,r.Key));
                        x.WriteEndElement(); // EmbeddedResource
                    }
                    x.WriteEndElement(); // ItemGroup

                    x.WriteStartElement("ItemGroup", ns);
                    foreach (var parameter in param.ReferencedAssemblies)
                    {
                        x.WriteStartElement("Reference", ns);
                        x.WriteAttributeString("Include", root(dir,parameter));
                        x.WriteEndElement(); // Reference
                    }
                    x.WriteEndElement(); // ItemGroup

                    // CS
                    x.WriteStartElement("ItemGroup", ns);
                    x.WriteStartElement("Compile", ns);
                    x.WriteAttributeString("Include", root(dir,cs));
                    x.WriteEndElement();
                    x.WriteEndElement(); // CS

                    if (prov35)
                    {
                        if (options.Icon != null)
                        {
                            x.WriteStartElement("ItemGroup", ns);
                            x.WriteStartElement("None", ns);
                            x.WriteAttributeString("Include",str_icon);
                            x.WriteEndElement();
                            x.WriteEndElement(); // Icon
                        }
                        if (options.Manifest != null)
                        {
                            x.WriteStartElement("ItemGroup", ns);
                            x.WriteStartElement("None", ns);
                            x.WriteAttributeString("Include", str_manifest);
                            x.WriteEndElement();
                            x.WriteEndElement(); // Manifest
                        }
                    }
                    else
                    {
                        x.WriteStartElement("ItemGroup", ns);
                        x.WriteStartElement("None", ns);
                        x.WriteAttributeString("Include", str_w32resources);
                        x.WriteEndElement();
                        x.WriteEndElement(); // w32resources
                    }

                    x.WriteEndElement(); // Project
                }

                const string tpl = @"Microsoft Visual Studio Solution File, Format Version 10.00
            # Visual Studio 2008
            Project(""${slnGuid}"") = ""${id}"", ""${id}.csproj"", ""${projGuid}""
            EndProject
            Global
            GlobalSection(SolutionConfigurationPlatforms) = preSolution
            Debug|Any CPU = Debug|Any CPU
            Release|Any CPU = Release|Any CPU
            EndGlobalSection
            GlobalSection(ProjectConfigurationPlatforms) = postSolution
            ${projGuid}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
            ${projGuid}.Debug|Any CPU.Build.0 = Debug|Any CPU
            ${projGuid}.Release|Any CPU.ActiveCfg = Release|Any CPU
            ${projGuid}.Release|Any CPU.Build.0 = Release|Any CPU
            EndGlobalSection
            GlobalSection(SolutionProperties) = preSolution
            HideSolutionNode = FALSE
            EndGlobalSection
            EndGlobal";
                File.WriteAllText(Path.ChangeExtension(projName, "sln"),
                                  tpl.Replace("${slnGuid}", Guid.NewGuid().ToString("B").ToUpper())
                                      .Replace("${projGuid}", projGuid.ToString("B").ToUpper())
                                      .Replace("${id}",id));

            }
        }
Exemplo n.º 2
0
        /// Produce solution files
        private static void beautifyOutput(bool prov35, CompiledOutputType outputtype, CompileOptions options, CompilerParameters param, Dictionary <string, string> resources, string moduleName, Version neededVersion)
        {
            string id       = Path.GetFileNameWithoutExtension(moduleName);
            string tempName = null;
            string projName = null;
            string cs       = null;


            foreach (string t in param.TempFiles)
            {
                if (!File.Exists(t))
                {
                    continue;
                }

                if (tempName == null)
                {
                    tempName = Path.GetFileNameWithoutExtension(t);
                }
                string ext     = Path.GetExtension(t).ToLower().TrimStart('.');
                string newName = Path.Combine(Path.GetDirectoryName(t), id + "." + ext);
                File.Delete(newName);
                if (ext == "cs")
                {
                    File.Move(t, newName);
                    cs = newName;
                }

                if (ext == "cmdline")
                {
                    string s = File.ReadAllText(t);

                    string csc = "csc.exe";
                    // Get compiler path
                    foreach (Version v in Utils.GetInstalledNETVersions())
                    {
                        if (neededVersion > v)
                        {
                            continue;
                        }
                        DirectoryInfo d = Utils.FindNETFrameworkDirectory(v);
                        if (d == null)
                        {
                            continue;
                        }
                        string fn = Path.Combine(d.FullName, "csc.exe");
                        if (File.Exists(fn))
                        {
                            csc = Utils.QuoteArg(fn);
                            break;
                        }
                    }

                    s = csc + " /noconfig " + s;
                    s = s.Replace(tempName + ".0", id);
                    s = s.Replace(tempName, id);

                    newName  = Path.Combine(Path.GetDirectoryName(t), "compile_" + id + ".bat");
                    projName = Path.Combine(Path.GetDirectoryName(t), id + ".csproj");
                    File.Delete(newName);
                    File.WriteAllText(newName, s);
                }
                File.Delete(t);
            }

            // Write project file
            if (projName != null)
            {
                Guid   projGuid = Guid.NewGuid();
                string dir      = Path.GetFullPath(Path.GetDirectoryName(projName));
                using (XmlWriter x = XmlWriter.Create(projName, new XmlWriterSettings()
                {
                    Indent = true, IndentChars = "  "
                }))
                {
                    string ns = "http://schemas.microsoft.com/developer/msbuild/2003";
                    x.WriteStartElement("Project", ns);
                    if (prov35)
                    {
                        x.WriteAttributeString("ToolsVersion", (Environment.Version.Major >= 4)?"4.0.30319": "3.5");
                    }
                    x.WriteAttributeString("DefaultTargets", "Build");

                    x.WriteStartElement("PropertyGroup", ns);
                    x.WriteStartElement("Configuration"); x.WriteAttributeString("Condition", " '$(Configuration)' == '' "); x.WriteValue("Debug"); x.WriteEndElement();
                    x.WriteStartElement("Platform"); x.WriteAttributeString("Condition", " '$(Platform)' == '' "); x.WriteValue("AnyCPU"); x.WriteEndElement();
                    x.WriteElementString("ProductVersion", "9.0.30729");
                    x.WriteElementString("SchemaVersion", "2.0");
                    x.WriteElementString("ProjectGuid", projGuid.ToString("B").ToUpper());

                    if (outputtype == CompiledOutputType.Library)
                    {
                        x.WriteElementString("OutputType", "Library");
                    }
                    else if (outputtype == CompiledOutputType.WindowsExe)
                    {
                        x.WriteElementString("OutputType", "WinExe");
                    }
                    else
                    {
                        x.WriteElementString("OutputType", "Exe");
                    }
                    x.WriteElementString("AssemblyName", Path.GetFileNameWithoutExtension(projName));
                    x.WriteElementString("ErrorReport", "prompt");
                    x.WriteElementString("WarningLevel", "4");
                    if (prov35)
                    {
                        if (options.Icon != null)
                        {
                            x.WriteElementString("ApplicationIcon", str_icon);
                        }
                        if (options.Manifest != null)
                        {
                            x.WriteElementString("ApplicationManifest", str_manifest);
                        }
                    }
                    else
                    {
                        x.WriteElementString("Win32Resource", str_w32resources);
                    }

                    x.WriteEndElement(); // Property group

                    x.WriteStartElement("PropertyGroup", ns);
                    x.WriteAttributeString("Condition", " '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ");
                    x.WriteElementString("DebugType", "Full");
                    x.WriteElementString("DebugSymbols", "true");
                    x.WriteElementString("OutputPath", "bin\\Debug\\");
                    x.WriteElementString("DefineConstants", "DEBUG;TRACE;");
                    x.WriteElementString("Optimize", "false");
                    x.WriteEndElement(); // Property group

                    x.WriteStartElement("PropertyGroup", ns);
                    x.WriteAttributeString("Condition", " '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ");
                    x.WriteElementString("DebugType", "pdbonly");
                    x.WriteElementString("DebugSymbols", "false");
                    x.WriteElementString("OutputPath", "bin\\Release\\");
                    x.WriteElementString("DefineConstants", "TRACE;");
                    x.WriteElementString("Optimize", "true");
                    x.WriteEndElement(); // Property group

                    x.WriteStartElement("Import", ns);
                    x.WriteAttributeString("Project", "$(MSBuildToolsPath)\\Microsoft.CSharp.targets");
                    x.WriteEndElement(); // Import

                    x.WriteStartElement("ItemGroup", ns);
                    foreach (var r in resources)
                    {
                        x.WriteStartElement("EmbeddedResource", ns);
                        x.WriteAttributeString("Include", root(dir, r.Key));
                        x.WriteEndElement(); // EmbeddedResource
                    }
                    x.WriteEndElement();     // ItemGroup

                    x.WriteStartElement("ItemGroup", ns);
                    foreach (var parameter in param.ReferencedAssemblies)
                    {
                        x.WriteStartElement("Reference", ns);
                        x.WriteAttributeString("Include", root(dir, parameter));
                        x.WriteEndElement(); // Reference
                    }
                    x.WriteEndElement();     // ItemGroup

                    // CS
                    x.WriteStartElement("ItemGroup", ns);
                    x.WriteStartElement("Compile", ns);
                    x.WriteAttributeString("Include", root(dir, cs));
                    x.WriteEndElement();
                    x.WriteEndElement(); // CS

                    if (prov35)
                    {
                        if (options.Icon != null)
                        {
                            x.WriteStartElement("ItemGroup", ns);
                            x.WriteStartElement("None", ns);
                            x.WriteAttributeString("Include", str_icon);
                            x.WriteEndElement();
                            x.WriteEndElement(); // Icon
                        }
                        if (options.Manifest != null)
                        {
                            x.WriteStartElement("ItemGroup", ns);
                            x.WriteStartElement("None", ns);
                            x.WriteAttributeString("Include", str_manifest);
                            x.WriteEndElement();
                            x.WriteEndElement(); // Manifest
                        }
                    }
                    else
                    {
                        x.WriteStartElement("ItemGroup", ns);
                        x.WriteStartElement("None", ns);
                        x.WriteAttributeString("Include", str_w32resources);
                        x.WriteEndElement();
                        x.WriteEndElement(); // w32resources
                    }

                    x.WriteEndElement(); // Project
                }

                const string tpl = @"Microsoft Visual Studio Solution File, Format Version 10.00
# Visual Studio 2008
Project(""${slnGuid}"") = ""${id}"", ""${id}.csproj"", ""${projGuid}""
EndProject
Global
	GlobalSection(SolutionConfigurationPlatforms) = preSolution
		Debug|Any CPU = Debug|Any CPU
		Release|Any CPU = Release|Any CPU
	EndGlobalSection
	GlobalSection(ProjectConfigurationPlatforms) = postSolution
		${projGuid}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
		${projGuid}.Debug|Any CPU.Build.0 = Debug|Any CPU
		${projGuid}.Release|Any CPU.ActiveCfg = Release|Any CPU
		${projGuid}.Release|Any CPU.Build.0 = Release|Any CPU
	EndGlobalSection
	GlobalSection(SolutionProperties) = preSolution
		HideSolutionNode = FALSE
	EndGlobalSection
EndGlobal";
                File.WriteAllText(Path.ChangeExtension(projName, "sln"),
                                  tpl.Replace("${slnGuid}", Guid.NewGuid().ToString("B").ToUpper())
                                  .Replace("${projGuid}", projGuid.ToString("B").ToUpper())
                                  .Replace("${id}", id));
            }
        }
Exemplo n.º 3
0
        /// <summary>
        /// Compile code
        /// </summary>
        /// <param name="outputtype">Type of the assembly to produce</param>
        /// <param name="code">C# code</param>
        /// <param name="moduleName">Name of the generated module</param>
        /// <param name="options">Compilation options</param>
        /// <returns></returns>
        public Assembly Compile(CompiledOutputType outputtype, 
            string code,
            string moduleName,
            CompileOptions options)
        {
            string codeOutputDirectory = null;
            if (options != null && !string.IsNullOrEmpty(options.CodeOutputDirectory))
            {
                Directory.CreateDirectory(options.CodeOutputDirectory);
                codeOutputDirectory = Path.GetFullPath(options.CodeOutputDirectory);
            }

            // Check that we have .NET
            if (MaxAvailableNETVersion < _neededVersion)
                throw new ParsingException(string.Format(
                                              ".NET v{0}.{1} is required to compile this script. .NET v{2}.{3} is installed.",
                                              _neededVersion.Major, _neededVersion.Minor, MaxAvailableNETVersion.Major, MaxAvailableNETVersion.Minor));

            // .NET 3.0 missing method fix
            bool prov35 = (MaxAvailableNETVersion >= new Version(3, 5));

            // Proceed with the gory details
            CompilerParameters param = new CompilerParameters();
            if (outputtype == CompiledOutputType.InMemoryAssembly )
            {
                param.GenerateExecutable = false;

                // If codeoutput directory is set, generate DLLs with debug info for <code> debuggin
                param.GenerateInMemory = false;
                param.IncludeDebugInformation = (codeOutputDirectory != null);
            }
            else
            {
                param.GenerateExecutable = (outputtype == CompiledOutputType.ConsoleExe || outputtype == CompiledOutputType.WindowsExe);
                param.GenerateInMemory = false;
                param.IncludeDebugInformation = (codeOutputDirectory != null);
                param.OutputAssembly = moduleName;

                var dir = Path.GetDirectoryName(moduleName);
                if (!string.IsNullOrEmpty(dir) && (codeOutputDirectory != null) && !Directory.Exists(dir))
                    Directory.CreateDirectory(dir);

            }

            param.WarningLevel = 0;
            switch (outputtype)
            {
                case CompiledOutputType.Library:
                    param.CompilerOptions += " /target:library";
                    break;
                case CompiledOutputType.ConsoleExe:
                    param.CompilerOptions += " /target:exe";
                    break;
                case CompiledOutputType.WindowsExe:
                    param.CompilerOptions += " /target:winexe";
                    break;
            }
            CompilerResults cr;
            List<string> toDelete = new List<string>();
            Dictionary<string,bool> embedded=new Dictionary<string, bool>();

            try
            {
                if (options!=null && options.Manifest!=null)
                {
                    // Only C# 3.5 can do manifests & icons separately. If compiled with .NET 2.0 there will be no file version
                    if (prov35)
                    {
                        string wm = getTempFilename(codeOutputDirectory, str_manifest);
                        toDelete.Add(wm);
                        File.WriteAllBytes(wm, options.Manifest);
                        string wi = getTempFilename(codeOutputDirectory, str_icon);
                        toDelete.Add(wi);
                        File.WriteAllBytes(wi, options.Icon);
                        param.CompilerOptions += " " + Utils.QuoteArg("/win32manifest:" + wm) + " " + Utils.QuoteArg("/win32icon:" + wi);
                    }
                    else
                    {
                        string w32 = getTempFilename(codeOutputDirectory, str_w32resources);
                        toDelete.Add(w32);
                        File.WriteAllBytes(w32, options.Compiled);
                        param.Win32Resource = w32;
                    }
                }

                if (options!=null && options.EntryPoint != null)
                    param.MainClass = options.EntryPoint;

                bool allStrong = true;
                Dictionary<string,string> resources=new Dictionary<string, string>();
                foreach (Ref r in _references)
                {
                    string location = r.From;
                    string dllName = string.Empty;
                    if (!string.IsNullOrEmpty(r.Name))
                    {
                        dllName = new AssemblyName(r.Name).Name + ".dll";
                    }

                    if (string.IsNullOrEmpty(location) && options != null && options.StreamProvider != null)
                    {
                        using (var v = options.StreamProvider(dllName))
                            if (v != null)
                            {
                                location = getTempFilename(codeOutputDirectory, str_references+Path.GetFileName(dllName));
                                toDelete.Add(location);
                                using (FileStream fs = new FileStream(location, FileMode.Create, FileAccess.Write, FileShare.Read))
                                    v.WriteTo(fs);
                            }
                    }
                    if (string.IsNullOrEmpty(location))
                    {
                        location = r.ForceLoad(_verboseWriter).Location;
                    }
                    if (string.IsNullOrEmpty(location))
                        throw new FileNotFoundException(string.Format("Referenced assembly {0} could not be found", r));

                    param.ReferencedAssemblies.Add(location);

                    if (options != null && moduleName != null && r.Embed && (CompiledOutputType.WindowsExe == outputtype || CompiledOutputType.ConsoleExe == outputtype) && options.StreamProvider != null)
                    {
                        MemoryStream v= options.StreamProvider(dllName + ".gz");
                        if (!string.IsNullOrEmpty(r.Name))
                        {
                            var n = new AssemblyName(r.Name);
                            if (n.GetPublicKeyToken() == null || n.GetPublicKeyToken().Length == 0)
                            {
                                _verboseWriter.WriteVerbose("Compile> Embedded assembly " + r.Name + " does not have a strong name.");
                                allStrong = false;
                            }
                        }
                        if (!embedded.ContainsKey(dllName))
                        {
                            string prefix = "XSharper.Embedded.Assemblies.";
                            // Let's be nice here, and compress the dll a bit
                            string complocation = createResource(resources, v, location, prefix + dllName, codeOutputDirectory, str_resources + prefix.Replace(".", "\\"));
                            if (complocation != null)
                                toDelete.Add(complocation);
                            embedded[dllName] = true;
                        }
                    }
                }
                // If user wanted any files, add them too
                if (options != null && options.FilesToEmbed != null)
                {
                    foreach (var pair in options.FilesToEmbed)
                    {
                        string name = (pair.IsAssembly) ? "XSharper.Embedded.Assemblies." : "XSharper.Embedded.Files.";
                        if (pair.IsAssembly)
                        {
                            _verboseWriter.WriteVerbose("Compile> Getting assembly name of " + pair.Location);
                            var pkt = AssemblyName.GetAssemblyName(pair.Location).GetPublicKeyToken();
                            if (pkt == null || pkt.Length == 0)
                            {
                                _verboseWriter.WriteVerbose("Compile> Embedded assembly " + pair.Location + " does not have a strong name.");
                                allStrong = false;
                            }
                        }
                        string complocation = createResource(resources, null, pair.Location, name + new FileInfo(pair.StreamName).Name, codeOutputDirectory, str_resources + name.Replace(".", "\\"));
                        if (complocation != null)
                            toDelete.Add(complocation);
                    }

                    if (allStrong)
                    {
                        string location = getTempFilename(codeOutputDirectory, str_resources+"XSharper\\Embedded\\Assemblies\\AllStrongName.flag");
                        toDelete.Add(location);
                        using (FileStream fs = new FileStream(location, FileMode.Create, FileAccess.Write, FileShare.Read))
                            fs.WriteByte((byte) '1');
                    }
                }

                if (codeOutputDirectory != null)
                    param.TempFiles = new TempFileCollection(codeOutputDirectory, true);
                foreach (var resource in resources)
                    param.CompilerOptions += " \"/res:" + resource.Key + "," + resource.Value + "\" ";
                if (options!=null && options.ExtraOptions != null)
                    param.CompilerOptions += " " + options.ExtraOptions;

                CSharpCodeProvider prov;
                if (!prov35)
                    prov=new CSharpCodeProvider();
                else
                {
                    Dictionary<string, string> providerOptions = new Dictionary<string, string>();
                    if (Environment.Version.Major>=4)
                        providerOptions.Add("CompilerVersion", string.Format("v{0}", "4.0"));
                    else
                        providerOptions.Add("CompilerVersion", string.Format("v{0}", "3.5"));

                    // Must do it this way, to prevent loading errors on machines with .net 2.0
                    prov = (CSharpCodeProvider) Activator.CreateInstance(typeof (CSharpCodeProvider), new object[] {providerOptions});
                }

                _verboseWriter.WriteVerbose("Compile> " + Dump.ToDump(param));
                cr = prov.CompileAssemblyFromSource(param, code);

                // Do some beautification
                if (outputtype != CompiledOutputType.InMemoryAssembly && codeOutputDirectory != null)
                    beautifyOutput(prov35, outputtype, options, param, resources, moduleName, _neededVersion);

                _verboseWriter.WriteVerbose("Compile> -- Completed --");
                // Fire compilation
                if (cr.Errors != null && cr.Errors.Count != 0)
                {
                    if (File.Exists(cr.PathToAssembly))
                        File.Delete(cr.PathToAssembly);
                    StringBuilder sb= new StringBuilder();
                    sb.Append("C# code compilation error:\n");
                    string[] lines = code.Split('\n');
                    foreach (CompilerError error in cr.Errors)
                    {
                        if (error != null)
                        {
                            string line = (error.Line >= 1 && error.Line <= lines.Length) ? lines[error.Line - 1] : "???";
                            sb.AppendLine(string.Format("Line: {0}\nError: {1}", line.TrimEnd(), error.ErrorText));
                        }
                    }
                    _verboseWriter.WriteVerbose("Compile> Errors: " + sb.ToString());

                    throw new ParsingException(sb.ToString());
                }

                if (outputtype == CompiledOutputType.InMemoryAssembly)
                {
                    byte[] asmData = File.ReadAllBytes(cr.PathToAssembly);
                    File.Delete(cr.PathToAssembly);
                    Assembly a=Assembly.Load(asmData);
                    return a;
                }
            }
            finally
            {
                if (string.IsNullOrEmpty(codeOutputDirectory) || outputtype == CompiledOutputType.InMemoryAssembly)
                    foreach (string na in toDelete)
                        File.Delete(na);
            }
            return outputtype == CompiledOutputType.InMemoryAssembly ? cr.CompiledAssembly : null;
        }
Exemplo n.º 4
0
        /// <summary>
        /// Compile code
        /// </summary>
        /// <param name="outputtype">Type of the assembly to produce</param>
        /// <param name="code">C# code</param>
        /// <param name="moduleName">Name of the generated module</param>
        /// <param name="options">Compilation options</param>
        /// <returns></returns>
        public Assembly Compile(CompiledOutputType outputtype,
                                string code,
                                string moduleName,
                                CompileOptions options)
        {
            string codeOutputDirectory = null;

            if (options != null && !string.IsNullOrEmpty(options.CodeOutputDirectory))
            {
                Directory.CreateDirectory(options.CodeOutputDirectory);
                codeOutputDirectory = Path.GetFullPath(options.CodeOutputDirectory);
            }

            // Check that we have .NET
            if (MaxAvailableNETVersion < _neededVersion)
            {
                throw new ParsingException(string.Format(
                                               ".NET v{0}.{1} is required to compile this script. .NET v{2}.{3} is installed.",
                                               _neededVersion.Major, _neededVersion.Minor, MaxAvailableNETVersion.Major, MaxAvailableNETVersion.Minor));
            }

            // .NET 3.0 missing method fix
            bool prov35 = (MaxAvailableNETVersion >= new Version(3, 5));



            // Proceed with the gory details
            CompilerParameters param = new CompilerParameters();

            if (outputtype == CompiledOutputType.InMemoryAssembly)
            {
                param.GenerateExecutable = false;

                // If codeoutput directory is set, generate DLLs with debug info for <code> debuggin
                param.GenerateInMemory        = false;
                param.IncludeDebugInformation = (codeOutputDirectory != null);
            }
            else
            {
                param.GenerateExecutable      = (outputtype == CompiledOutputType.ConsoleExe || outputtype == CompiledOutputType.WindowsExe);
                param.GenerateInMemory        = false;
                param.IncludeDebugInformation = (codeOutputDirectory != null);
                param.OutputAssembly          = moduleName;

                var dir = Path.GetDirectoryName(moduleName);
                if (!string.IsNullOrEmpty(dir) && (codeOutputDirectory != null) && !Directory.Exists(dir))
                {
                    Directory.CreateDirectory(dir);
                }
            }

            param.WarningLevel = 0;
            switch (outputtype)
            {
            case CompiledOutputType.Library:
                param.CompilerOptions += " /target:library";
                break;

            case CompiledOutputType.ConsoleExe:
                param.CompilerOptions += " /target:exe";
                break;

            case CompiledOutputType.WindowsExe:
                param.CompilerOptions += " /target:winexe";
                break;
            }
            CompilerResults           cr;
            List <string>             toDelete = new List <string>();
            Dictionary <string, bool> embedded = new Dictionary <string, bool>();



            try
            {
                if (options != null && options.Manifest != null)
                {
                    // Only C# 3.5 can do manifests & icons separately. If compiled with .NET 2.0 there will be no file version
                    if (prov35)
                    {
                        string wm = getTempFilename(codeOutputDirectory, str_manifest);
                        toDelete.Add(wm);
                        File.WriteAllBytes(wm, options.Manifest);
                        string wi = getTempFilename(codeOutputDirectory, str_icon);
                        toDelete.Add(wi);
                        File.WriteAllBytes(wi, options.Icon);
                        param.CompilerOptions += " " + Utils.QuoteArg("/win32manifest:" + wm) + " " + Utils.QuoteArg("/win32icon:" + wi);
                    }
                    else
                    {
                        string w32 = getTempFilename(codeOutputDirectory, str_w32resources);
                        toDelete.Add(w32);
                        File.WriteAllBytes(w32, options.Compiled);
                        param.Win32Resource = w32;
                    }
                }

                if (options != null && options.EntryPoint != null)
                {
                    param.MainClass = options.EntryPoint;
                }

                bool allStrong = true;
                Dictionary <string, string> resources = new Dictionary <string, string>();
                foreach (Ref r in _references)
                {
                    string location = r.From;
                    string dllName  = string.Empty;
                    if (!string.IsNullOrEmpty(r.Name))
                    {
                        dllName = new AssemblyName(r.Name).Name + ".dll";
                    }

                    if (string.IsNullOrEmpty(location) && options != null && options.StreamProvider != null)
                    {
                        using (var v = options.StreamProvider(dllName))
                            if (v != null)
                            {
                                location = getTempFilename(codeOutputDirectory, str_references + Path.GetFileName(dllName));
                                toDelete.Add(location);
                                using (FileStream fs = new FileStream(location, FileMode.Create, FileAccess.Write, FileShare.Read))
                                    v.WriteTo(fs);
                            }
                    }
                    if (string.IsNullOrEmpty(location))
                    {
                        location = r.ForceLoad(_verboseWriter).Location;
                    }
                    if (string.IsNullOrEmpty(location))
                    {
                        throw new FileNotFoundException(string.Format("Referenced assembly {0} could not be found", r));
                    }

                    param.ReferencedAssemblies.Add(location);

                    if (options != null && moduleName != null && r.Embed && (CompiledOutputType.WindowsExe == outputtype || CompiledOutputType.ConsoleExe == outputtype) && options.StreamProvider != null)
                    {
                        MemoryStream v = options.StreamProvider(dllName + ".gz");
                        if (!string.IsNullOrEmpty(r.Name))
                        {
                            var n = new AssemblyName(r.Name);
                            if (n.GetPublicKeyToken() == null || n.GetPublicKeyToken().Length == 0)
                            {
                                _verboseWriter.WriteVerbose("Compile> Embedded assembly " + r.Name + " does not have a strong name.");
                                allStrong = false;
                            }
                        }
                        if (!embedded.ContainsKey(dllName))
                        {
                            string prefix = "XSharper.Embedded.Assemblies.";
                            // Let's be nice here, and compress the dll a bit
                            string complocation = createResource(resources, v, location, prefix + dllName, codeOutputDirectory, str_resources + prefix.Replace(".", "\\"));
                            if (complocation != null)
                            {
                                toDelete.Add(complocation);
                            }
                            embedded[dllName] = true;
                        }
                    }
                }
                // If user wanted any files, add them too
                if (options != null && options.FilesToEmbed != null)
                {
                    foreach (var pair in options.FilesToEmbed)
                    {
                        string name = (pair.IsAssembly) ? "XSharper.Embedded.Assemblies." : "XSharper.Embedded.Files.";
                        if (pair.IsAssembly)
                        {
                            _verboseWriter.WriteVerbose("Compile> Getting assembly name of " + pair.Location);
                            var pkt = AssemblyName.GetAssemblyName(pair.Location).GetPublicKeyToken();
                            if (pkt == null || pkt.Length == 0)
                            {
                                _verboseWriter.WriteVerbose("Compile> Embedded assembly " + pair.Location + " does not have a strong name.");
                                allStrong = false;
                            }
                        }
                        string complocation = createResource(resources, null, pair.Location, name + new FileInfo(pair.StreamName).Name, codeOutputDirectory, str_resources + name.Replace(".", "\\"));
                        if (complocation != null)
                        {
                            toDelete.Add(complocation);
                        }
                    }

                    if (allStrong)
                    {
                        string location = getTempFilename(codeOutputDirectory, str_resources + "XSharper\\Embedded\\Assemblies\\AllStrongName.flag");
                        toDelete.Add(location);
                        using (FileStream fs = new FileStream(location, FileMode.Create, FileAccess.Write, FileShare.Read))
                            fs.WriteByte((byte)'1');
                    }
                }

                if (codeOutputDirectory != null)
                {
                    param.TempFiles = new TempFileCollection(codeOutputDirectory, true);
                }
                foreach (var resource in resources)
                {
                    param.CompilerOptions += " \"/res:" + resource.Key + "," + resource.Value + "\" ";
                }
                if (options != null && options.ExtraOptions != null)
                {
                    param.CompilerOptions += " " + options.ExtraOptions;
                }

                CSharpCodeProvider prov;
                if (!prov35)
                {
                    prov = new CSharpCodeProvider();
                }
                else
                {
                    Dictionary <string, string> providerOptions = new Dictionary <string, string>();
                    if (Environment.Version.Major >= 4)
                    {
                        providerOptions.Add("CompilerVersion", string.Format("v{0}", "4.0"));
                    }
                    else
                    {
                        providerOptions.Add("CompilerVersion", string.Format("v{0}", "3.5"));
                    }

                    // Must do it this way, to prevent loading errors on machines with .net 2.0
                    prov = (CSharpCodeProvider)Activator.CreateInstance(typeof(CSharpCodeProvider), new object[] { providerOptions });
                }

                _verboseWriter.WriteVerbose("Compile> " + Dump.ToDump(param));
                cr = prov.CompileAssemblyFromSource(param, code);

                // Do some beautification
                if (outputtype != CompiledOutputType.InMemoryAssembly && codeOutputDirectory != null)
                {
                    beautifyOutput(prov35, outputtype, options, param, resources, moduleName, _neededVersion);
                }

                _verboseWriter.WriteVerbose("Compile> -- Completed --");
                // Fire compilation
                if (cr.Errors != null && cr.Errors.Count != 0)
                {
                    if (File.Exists(cr.PathToAssembly))
                    {
                        File.Delete(cr.PathToAssembly);
                    }
                    StringBuilder sb = new StringBuilder();
                    sb.Append("C# code compilation error:\n");
                    string[] lines = code.Split('\n');
                    foreach (CompilerError error in cr.Errors)
                    {
                        if (error != null)
                        {
                            string line = (error.Line >= 1 && error.Line <= lines.Length) ? lines[error.Line - 1] : "???";
                            sb.AppendLine(string.Format("Line: {0}\nError: {1}", line.TrimEnd(), error.ErrorText));
                        }
                    }
                    _verboseWriter.WriteVerbose("Compile> Errors: " + sb.ToString());

                    throw new ParsingException(sb.ToString());
                }

                if (outputtype == CompiledOutputType.InMemoryAssembly)
                {
                    byte[] asmData = File.ReadAllBytes(cr.PathToAssembly);
                    File.Delete(cr.PathToAssembly);
                    Assembly a = Assembly.Load(asmData);
                    return(a);
                }
            }
            finally
            {
                if (string.IsNullOrEmpty(codeOutputDirectory) || outputtype == CompiledOutputType.InMemoryAssembly)
                {
                    foreach (string na in toDelete)
                    {
                        File.Delete(na);
                    }
                }
            }
            return(outputtype == CompiledOutputType.InMemoryAssembly ? cr.CompiledAssembly : null);
        }