private static void doCodeGeneration(ScriptContext context, Script script) { if (!isCodeGeneration(context)) return; context.Compiler.AddReference(null,typeof(System.Runtime.Remoting.Channels.Ipc.IpcChannel).Assembly.FullName,false,false,null); if (context.IsSet(xs.save) && script != null) { context.WriteLine(OutputType.Info, string.Format("Saving script to {0} ...", context[xs.save])); using (new ScriptContextScope(context)) script.Save(context.GetString(xs.save)); context.WriteLine(OutputType.Info, string.Format("Script file {0} saved...", context[xs.save])); } if (context.IsSet(xs.genxsd)) { context.WriteLine(OutputType.Info, string.Format("Generating XML schema ...")); XmlSchema x = generateSchema(context); string sf = context.GetString(xs.genxsd); sf=Path.GetFullPath((sf == "*") ? x.Id + ".xsd" : sf); using (StreamWriter target = new StreamWriter(sf, false)) x.Write(target); context.WriteLine(OutputType.Info, string.Format("XML schema saved to {0} ...", sf)); } // Generate source code StringWriter source = new StringWriter(); string entryPoint = null; if (script != null && (context.IsSet(xs.genlibrary) || context.IsSet(xs.genexe) || context.IsSet(xs.genwinexe) || context.IsSet(xs.gencs))) { context.WriteLine(OutputType.Info, "Generating C# source code..."); SharpCodeGenerator codeGenerator = new SharpCodeGenerator(context.Compiler); if (context.IsSet(xs.@namespace)) codeGenerator.Namespace = context.GetString(xs.@namespace); string baseName = Path.GetFileNameWithoutExtension(script.Location).ToLower(); if (script.Id!=null) baseName = script.Id; baseName = Utils.FixFilename(baseName); if (context.IsSet(xs.@class)) codeGenerator.Class = context.GetString(xs.@class); else { string cl; cl = baseName; if (char.IsDigit(cl[0])) cl = "C" + cl; if (!char.IsUpper(cl[0])) cl = cl.Substring(0, 1).ToUpperInvariant() + cl.Substring(1); cl = SharpCodeGenerator.ToValidName(cl); if (cl == "Script" || cl == "Run") cl = "C" + cl; codeGenerator.Class = cl; } string pref = string.Empty; if (!string.IsNullOrEmpty(context.CodeOutputDirectory)) pref = Path.Combine(context.CodeOutputDirectory, "bin\\Debug\\"); if (context.IsSet(xs.genexe) && context.GetString(xs.genexe) == "*") context[xs.genexe] = pref+baseName + ".exe"; if (context.IsSet(xs.genwinexe) && context.GetString(xs.genwinexe) == "*") context[xs.genwinexe] = pref + baseName + ".exe"; if (context.IsSet(xs.genlibrary) && context.GetString(xs.genlibrary) == "*") context[xs.genlibrary] = pref + baseName + ".dll"; if (context.IsSet(xs.gencs) && context.GetString(xs.gencs) == "*") context[xs.gencs] = baseName + ".cs"; GeneratorOptions options = GeneratorOptions.None; if (context.IsSet(xs.genexe)) options |= GeneratorOptions.IncludeSource | GeneratorOptions.ForExe | GeneratorOptions.CreateMain; if (context.IsSet(xs.genwinexe)) options |= GeneratorOptions.IncludeSource | GeneratorOptions.ForExe | GeneratorOptions.CreateMain | GeneratorOptions.WinExe; if (context.IsSet(xs.genlibrary)) options |= GeneratorOptions.IncludeSource | GeneratorOptions.ForExe; if (context.GetBool(xs.main, false)) options |= GeneratorOptions.CreateMain; if (context.GetBool(xs.forcenet20, false)) options |= GeneratorOptions.ForceNet20; if (context.CodeOutputDirectory == null && !context.IsSet(xs.gencs)) options |= GeneratorOptions.ForceNet20; // this is a bit faster if (context.GetBool(xs.noSrc, false)) options &= ~GeneratorOptions.IncludeSource; codeGenerator.Generate(context, source, script, options); if (context.IsSet(xs.genexe) || context.IsSet(xs.genwinexe)) entryPoint = codeGenerator.Namespace + "." + codeGenerator.Class + "Program"; } // Save it to disk, if necessary string code = source.GetStringBuilder().ToString(); if (script != null && context.IsSet(xs.gencs)) { using (StreamWriter sourceDisk = new StreamWriter(context.GetString(xs.gencs), false)) { sourceDisk.Write(code); } context.WriteLine(OutputType.Info, string.Format("C# source code saved to {0} ...", context[xs.gencs])); } // Load the other part from resources if (script != null && (context.IsSet(xs.genexe) || context.IsSet(xs.genwinexe) || context.IsSet(xs.genlibrary))) { CompiledOutputType outType; string e; if (context.IsSet(xs.genexe)) { e = context.GetString(xs.genexe); outType = CompiledOutputType.ConsoleExe; } else if (context.IsSet(xs.genwinexe)) { e = context.GetString(xs.genwinexe); outType = CompiledOutputType.WindowsExe; } else { e = context.GetString(xs.genlibrary); outType = CompiledOutputType.Library; } context.WriteLine(OutputType.Info, string.Format("Compiling {0}...", e)); var copt = new CompileOptions { ExtraOptions = context.GetString(xs.compilerOptions, null), CodeOutputDirectory=context.CodeOutputDirectory, StreamProvider=context.FindResourceMemoryStream, FilesToEmbed = context.GetFilesToEmbed(), EntryPoint=entryPoint, }; if (context.IsSet(xs.genexe) || context.IsSet(xs.genwinexe)) { if (script.RequireAdmin!=RequireAdminMode.User) { copt.Compiled = AppDomainLoader.TryLoadResourceStream(@"Manifests.requireAdministrator.res").ToArray(); copt.Manifest = AppDomainLoader.TryLoadResourceStream(@"Manifests.requireAdministrator.manifest").ToArray(); } else { copt.Compiled = AppDomainLoader.TryLoadResourceStream(@"Manifests.asInvoker.res").ToArray(); copt.Manifest = AppDomainLoader.TryLoadResourceStream(@"Manifests.asInvoker.manifest").ToArray(); } if (context.IsSet(xs.icon)) copt.Icon = context.ReadBytes(context.GetStr(xs.icon)); else copt.Icon = AppDomainLoader.TryLoadResourceStream(@"Source.xsh.ico").ToArray(); } // If we're building .EXE, add a reference to ZipLib. We don't want to do it // unnecessarily to save time, and also allow XSharper.Core use w/o ZipLib, so the reference is added only if it's loaded foreach (var ass in AppDomain.CurrentDomain.GetAssemblies()) if (ass.FullName != null && ass.FullName.Contains("ICSharpCode.SharpZipLib")) { context.Compiler.AddReference(null, ass.FullName, true, false,null); break; } context.Compiler.Compile(outType,code,e,copt); context.WriteLine(OutputType.Info, string.Format("Executable saved to {0} ...", e)); } }
/// 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)); } }
/// 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)); } }
/// <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; }
/// <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); }