private static string CreateProject(string scriptFile, string tempDir, ProcessSourceFile fileHandler, bool copyLocalAsm) { string srcProjDir = @"Lib\Debug\VS10.0"; //relative to CSSCRIPT_DIR string scHomeDir = VS100IDE.GetEnvironmentVariable("CSSCRIPT_DIR"); string scriptShortName = Path.GetFileName(scriptFile); string projFile = Path.Combine(tempDir, "DebugScript.csproj"); string solutionFile = Path.Combine(tempDir, "DebugScript.sln"); //copy project template if (!Directory.Exists(tempDir)) Directory.CreateDirectory(tempDir); foreach (string file in Directory.GetFiles(Path.Combine(scHomeDir, srcProjDir))) { if (Path.GetExtension(file) != ".resx") { if (string.Compare(Path.GetFileName(file), "AssemblyInfo.cs", true) == 0) { using (StreamReader sr = new StreamReader(file)) using (StreamWriter sw = new StreamWriter(Path.Combine(tempDir, Path.GetFileName(file)))) { string code = sr.ReadToEnd().Replace("ScriptDebugger", Path.GetFileNameWithoutExtension(scriptFile)); sw.Write(code); } } else { File.Copy(file, Path.Combine(tempDir, Path.GetFileName(file)), true); } } } //update project template with script specific data VS100IDE ide = new VS100IDE(); ScriptParser parser = new ScriptParser(scriptFile, Script.SearchDirs, VS100IDE.isolating); AssemblyResolver asmResolver = new AssemblyResolver(); foreach (string dir in parser.SearchDirs) AddSearchDir(dir); string resxSrcFile = Path.Combine(Path.Combine(scHomeDir, srcProjDir), "Form1.resx"); bool XAML = false; bool WWF = false; ArrayList importerdScripts = new ArrayList(); ArrayList precompilibleScripts = new ArrayList(); importerdScripts.AddRange(parser.SaveImportedScripts()); string srcFile = fileHandler(scriptFile, tempDir); XAML = srcFile.ToLower().EndsWith(".xaml"); string associatedXml = FindAssociatedXml(srcFile, (string[])importerdScripts.ToArray(typeof(string))); string precompiler = ""; if (UsesPreprocessor(srcFile, out precompiler)) precompilibleScripts.Add(new string[] { srcFile, precompiler }); if (VS100IDE.IsResxRequired(srcFile) && associatedXml == "") ide.InsertFile(srcFile, projFile, resxSrcFile, ""); else { if (associatedXml != "") ide.InsertXamlCSFile(srcFile, projFile, associatedXml); else ide.InsertFile(srcFile, projFile, "", ""); } foreach (string file in importerdScripts) { if (UsesPreprocessor(file, out precompiler)) precompilibleScripts.Add(new string[] { file, precompiler }); srcFile = fileHandler(file, tempDir); associatedXml = FindAssociatedXml(srcFile, (string[])importerdScripts.ToArray(typeof(string))); XAML = srcFile.ToLower().EndsWith(".xaml"); if (!Path.GetFileName(srcFile).StartsWith("i_") && VS100IDE.IsResxRequired(srcFile) && associatedXml == "") { ide.InsertFile(srcFile, projFile, resxSrcFile, ""); } else { if (associatedXml != "") ide.InsertXamlCSFile(srcFile, projFile, associatedXml); else ide.InsertFile(srcFile, projFile, "", ""); } } if (XAML) ide.InsertImport(@"$(MSBuildBinPath)\Microsoft.WinFX.targets", projFile); ArrayList referencedNamespaces = new ArrayList(parser.ReferencedNamespaces); string[] defaultAsms = (CSScript.GlobalSettings.DefaultRefAssemblies ?? "") .Replace(" ", "") .Split(";,".ToCharArray()); referencedNamespaces.AddRange(defaultAsms); if (precompilibleScripts.Count > 0) { referencedNamespaces.Add("CSScriptLibrary"); Hashtable ht = new Hashtable(); foreach (string[] info in precompilibleScripts) { if (!ht.ContainsKey(info[1])) //to avoid duplication { ht[info[1]] = true; string t = Path.GetDirectoryName(scriptFile); ide.InsertFile(Path.Combine(Path.GetDirectoryName(scriptFile), info[1]), projFile, "", ""); } } string commands = ""; foreach (string[] info in precompilibleScripts) commands += "cscs.exe \"" + Path.Combine(Path.GetDirectoryName(scriptFile), info[1]) + "\" \"" + info[0] + "\" \"/primary:" + scriptFile + "\"" + "\r\n"; string firstPrecompiler = (precompilibleScripts[0] as string[])[1]; ide.InsertFile(Path.Combine(scHomeDir, "Lib\\precompile.part.cs"), projFile, "", firstPrecompiler); ide.InsertPreBuildEvent(commands, projFile); //<PropertyGroup> //<PreBuildEvent>cscs.exe "C:\cs-script\Dev\Macros C#\precompile.cs" "C:\cs-script\Dev\Macros C#\code.cs"</PreBuildEvent> //</PropertyGroup> } foreach (string name in referencedNamespaces) { bool ignore = false; foreach (string ignoreName in parser.IgnoreNamespaces) if (ignore = (name == ignoreName)) break; if (ignore) continue; string[] asmFiles = AssemblyResolver.FindAssembly(name, SearchDirs); foreach (string file in asmFiles) { if (!WWF && file.ToLower().IndexOf("system.workflow.runtime") != -1) WWF = true; if (!copyLocalAsm || file.IndexOf("assembly\\GAC") != -1 || file.IndexOf("assembly/GAC") != -1) ide.InsertReference(file, projFile); else { string asmCopy = Path.Combine(tempDir, Path.GetFileName(file)); File.Copy(file, asmCopy, true); ide.InsertReference(Path.GetFileName(asmCopy), projFile); } } } foreach (string asm in parser.ReferencedAssemblies) //some assemblies were referenced from code { foreach (string file in AssemblyResolver.FindAssembly(asm, SearchDirs)) { if (!WWF && file.ToLower().IndexOf("system.workflow.runtime") != -1) WWF = true; if (!copyLocalAsm || file.IndexOf("assembly\\GAC") != -1 || file.IndexOf("assembly\\GAC") != -1) ide.InsertReference(file, projFile); else { string asmCopy = Path.Combine(tempDir, Path.GetFileName(file)); if (Path.IsPathRooted(file) || File.Exists(file)) File.Copy(file, asmCopy, true); ide.InsertReference(Path.GetFileName(asmCopy), projFile); } } } //adjust project settings if (WWF) { ide.InsertProjectTypeGuids("{14822709-B5A1-4724-98CA-57A101D1B079};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}", projFile); ide.InsertImport(@"$(MSBuildExtensionsPath)\Microsoft\Windows Workflow Foundation\v3.0\Workflow.Targets", projFile); foreach (string file in importerdScripts) if (file.ToLower().IndexOf("designer.cs") != -1) { string className = Path.GetFileNameWithoutExtension(file.ToLower()).Replace(".designer", ""); string template = Path.Combine(tempDir, "wwf.layout"); string layoutFile = file.Replace("designer.cs", "layout"); if (copyLocalAsm) //isolating layoutFile = Path.Combine(Path.GetDirectoryName(projFile), Path.GetFileName(layoutFile)); File.Copy(template, layoutFile, true); ReplaceInFile(layoutFile, "WFInitialState", className + "InitialState"); ide.InsertResource(layoutFile, projFile); } } CSharpParser fileParser = new CSharpParser(scriptFile, true, new string[] { "//css_dbg", "//css_args", "//css_co" }); //foreach (string statement in fileParser.CustomDirectives["//css_dbg"] as List<string>)//should be reenabled when CS-Script is compiled for .NET 2.0 foreach (string statement in fileParser.CustomDirectives["//css_dbg"] as IEnumerable) foreach (string directive in statement.Split(',')) { string d = directive.Trim(); if (d.StartsWith("/t:")) ide.SetOutputType(d.Substring("/t:".Length), projFile); else if (d.StartsWith("/platform:")) ide.SetPlatformType(d.Substring("/platform:".Length), projFile, solutionFile); else if (d.Trim().StartsWith("/args:")) ide.SetArguments(d.Substring("/args:".Length), projFile + ".user"); } //foreach (string statement in fileParser.CustomDirectives["//css_args"] as List<string>) //should be reenabled when CS-Script is compiled for .NET 2.0 foreach (string statement in fileParser.CustomDirectives["//css_args"] as IEnumerable) foreach (string directive in statement.Split(',')) { string d = directive.Trim(); if (d.StartsWith("/co")) { string[] compilerOptions = d.Substring(4).Split(','); foreach (string option in compilerOptions) { string o = option.Trim(); if (o.StartsWith("/unsafe")) ide.SetAllowUnsafe(projFile); else if (o.StartsWith("/platform:")) ide.SetPlatformType(o.Substring("/platform:".Length), projFile, solutionFile); } } } foreach (string statement in fileParser.CustomDirectives["//css_co"] as IEnumerable) foreach (string directive in statement.Split(',')) { string d = directive.Trim(); if (d.StartsWith("/platform:")) ide.SetPlatformType(d.Substring("/platform:".Length), projFile, solutionFile); } Settings settings = GetSystemWideSettings(); if (settings != null) ide.SetTargetFramework(settings.TargetFramework, projFile); ide.SetWorkingDir(Path.GetDirectoryName(scriptFile), projFile + ".user"); if (!VS100IDE.isolating) ide.RemoveFile("AssemblyInfo.cs", projFile); string appConfigFile = ""; if (File.Exists(Path.ChangeExtension(scriptFile, ".cs.config"))) appConfigFile = Path.ChangeExtension(scriptFile, ".cs.config"); else if (File.Exists(Path.ChangeExtension(scriptFile, ".exe.config"))) appConfigFile = Path.ChangeExtension(scriptFile, ".exe.config"); if (appConfigFile != "") ide.InsertAppConfig(appConfigFile, projFile); /////////////////////////////////// //rename project files string newSolutionFile = Path.Combine(tempDir, Path.GetFileNameWithoutExtension(scriptFile) + " (script).sln"); string newProjectFile = Path.Combine(tempDir, Path.GetFileNameWithoutExtension(newSolutionFile) + ".csproj"); FileMove(solutionFile, newSolutionFile); FileMove(projFile, newProjectFile); FileMove(projFile + ".user", newProjectFile + ".user"); ReplaceInFile(newSolutionFile, Path.GetFileNameWithoutExtension(projFile), Path.GetFileNameWithoutExtension(newProjectFile)); ReplaceInFile(newProjectFile, "DebugScript", Path.GetFileNameWithoutExtension(scriptFile)); //remove xmlns="" VSProjectDoc.FixFile(newProjectFile); VSProjectDoc.FixFile(newProjectFile + ".user"); /////////////////////// return newSolutionFile; }
public static void Main(string[] args) { SetEnvironmentVariable("CSScriptDebugging", "VS10.0"); if (args.Length == 0 || (args.Length == 1 && (args[0] == "?" || args[0] == "/?" || args[0] == "-?" || args[0].ToLower() == "help"))) { Console.WriteLine(usage); } else if (args[0].Trim().ToLower() == "/prj") { scriptFile = ResolveScriptFile(args[1]); try { VS100IDE.IsolateProject(scriptFile, Path.Combine(Path.GetDirectoryName(scriptFile), Path.GetFileNameWithoutExtension(scriptFile))); } catch (Exception e) { MessageBox.Show("Specified file could not be linked to the temp project:\n" + e.Message); } } else if (args[0].Trim().ToLower() == "/r") { string projFile = args[1]; try { VS100IDE.RefreshProject(projFile); } catch (Exception e) { MessageBox.Show("Specified file could not be linked to the temp project:\n" + e.Message); } } else if (args[0].Trim().ToLower() == "/print") { try { // Note "/print" is to be only invoked from VSX, which can only be hosted by full VS. Thus "/print" and "/e" cannot come together. scriptFile = args[1]; ScriptParser parser = new ScriptParser(scriptFile, Script.SearchDirs, false); foreach (string dir in parser.SearchDirs) AddSearchDir(dir); Console.WriteLine("Src:{0}", scriptFile); foreach (string file in parser.SaveImportedScripts()) Console.WriteLine("Src:{0}", file); string[] defaultAsms = (CSScript.GlobalSettings.DefaultRefAssemblies ?? "") .Replace(" ", "") .Split(";,".ToCharArray()); List<string> referencedAssemblies = new List<string>(); List<string> referencedNamespaces = new List<string>(); referencedNamespaces.AddRange(parser.ReferencedNamespaces); referencedNamespaces.AddRange(defaultAsms); foreach (string name in referencedNamespaces) if (!parser.IgnoreNamespaces.Contains(name)) referencedAssemblies.AddRange(AssemblyResolver.FindAssembly(name, SearchDirs)); foreach (string asm in parser.ReferencedAssemblies) //some assemblies were referenced from code referencedAssemblies.AddRange(AssemblyResolver.FindAssembly(asm, SearchDirs)); foreach (string file in referencedAssemblies.Distinct()) Console.WriteLine("Asm:{0}", file); } catch (Exception e) { MessageBox.Show("Specified file could not be linked to the temp project:\n" + e.Message); } } else { try { bool doNotOpenIDE = false; IDEEditions edition = IDEEditions.normal; scriptFile = args[0]; if (args[0].Trim().ToLower() == "/e") { edition = IDEEditions.express; scriptFile = args[1]; } // Note "/noide" is to be only invoked from VSX, which can only be hosted by full VS. Thus "/noide" and "/e" cannot come together. if (args[0].Trim().ToLower() == "/noide") { doNotOpenIDE = true; scriptFile = args[1]; } scriptFile = ResolveScriptFile(scriptFile); RunPreScripts(scriptFile); string tempDir = Path.Combine(GetTempCSSDir(), Environment.TickCount.ToString()); string solutionFile = VS100IDE.CreateProject(scriptFile, tempDir); string projFile = Path.ChangeExtension(solutionFile, ".csproj"); //"lock" the directory to indicate that it is in use File.WriteAllText(Path.Combine(tempDir, "host.pid"), Process.GetCurrentProcess().Id.ToString()); //open project Environment.CurrentDirectory = Path.GetDirectoryName(scriptFile); Process myProcess = new Process(); myProcess.StartInfo.FileName = VS100IDE.GetIDEFile(edition); if (myProcess.StartInfo.FileName == "<not defined>") { if (edition == IDEEditions.express) myProcess.StartInfo.FileName = VS100IDE.GetIDEFile(IDEEditions.normal); else myProcess.StartInfo.FileName = VS100IDE.GetIDEFile(IDEEditions.express); } AddToRecentScripts(scriptFile); if (!doNotOpenIDE) { myProcess.StartInfo.Arguments = "\"" + solutionFile + "\" " + " /command Edit.OpenFile " + "\"" + scriptFile + "\""; //MessageBox.Show("About to start the VS2010"); myProcess.Start(); myProcess.WaitForExit(); } else { Console.WriteLine("Solution File: " + solutionFile); } if (doNotOpenIDE) { //calling party is responsible for cleanup } else { //do clean up foreach (string file in VS100IDE.GetImportedScripts(projFile)) { DeleteSatelliteFiles(file); if (Path.GetFileName(file).StartsWith("i_")) //imported modified files have name "i_file_XXXXXX.cs>" { DeleteSatelliteFiles(file); File.SetAttributes(file, FileAttributes.Normal); File.Delete(file); } } try { Directory.Delete(tempDir, true); } catch { } RunPostScripts(scriptFile); } } catch (Exception e) { MessageBox.Show("Specified file could not be linked to the temp project:\n" + e); } } }
void ProcessCompilingResult(CompilerResults results, CompilerParameters compilerParams, ScriptParser parser, string scriptFileName, string assemblyFileName, string[] additionalDependencies) { LastCompileResult = results; if (results.Errors.HasErrors) { CompilerException ex = CompilerException.Create(results.Errors, options.hideCompilerWarnings); if (options.syntaxCheck) Console.WriteLine("Compile: {0} error(s)\n{1}", ex.ErrorCount, ex.Message); else throw ex; } else { if (options.syntaxCheck) Console.WriteLine("Compile: OK"); if (options.verbose) { Console.WriteLine(" Compiler Output: ", options); foreach (CompilerError err in results.Errors) Console.WriteLine(" {0}({1},{2}):{3} {4} {5}", err.FileName, err.Line, err.Column, (err.IsWarning ? "warning" : "error"), err.ErrorNumber, err.ErrorText); Console.WriteLine("> ----------------", options); } if (!options.DBG) //.pdb and imported files might be needed for the debugger { parser.DeleteImportedFiles(); string pdbFile = Path.Combine(Path.GetDirectoryName(assemblyFileName), Path.GetFileNameWithoutExtension(assemblyFileName) + ".pdb"); Utils.FileDelete(pdbFile); } if (options.useCompiled) { if (options.useSmartCaching) { MetaDataItems depInfo = new MetaDataItems(); string[] searchDirs = Utils.RemovePathDuplicates(options.searchDirs); //save imported scripts info depInfo.AddItems(parser.ImportedFiles, false, searchDirs); //additionalDependencies (precompilers) are warranted to be as absolute path so no need to pass searchDirs or isAssembly depInfo.AddItems(additionalDependencies, false, new string[0]); //save referenced local assemblies info string[] newProbingDirs = depInfo.AddItems(compilerParams.ReferencedAssemblies, true, searchDirs); foreach (string dir in newProbingDirs) options.AddSearchDir(dir); //needed to be added at Compilation for further resolving during the Invoking stage depInfo.StampFile(assemblyFileName); } FileInfo scriptFile = new FileInfo(scriptFileName); FileInfo asmFile = new FileInfo(assemblyFileName); if (scriptFile != null && asmFile != null) { asmFile.LastWriteTimeUtc = scriptFile.LastWriteTimeUtc; } } } }
static public void Main(string[] args) { if (args.Length == 0 || (args.Length == 1 && (args[0] == "?" || args[0] == "/?" || args[0] == "-?" || args[0].ToLower() == "help"))) { Console.WriteLine(usage); } else if (args[0].Trim().ToLower() == "/i") { SharpDevelopIDE.InstallShellExtension(); } else if (args[0].Trim().ToLower() == "/u") { SharpDevelopIDE.UninstallShellExtension(); } else { try { FileInfo info = new FileInfo(args[0]); scriptFile = info.FullName; string srcProjDir = @"Lib\Debug\#D1.1"; //relative to CSSCRIPT_DIR string scHomeDir = SharpDevelopIDE.GetEnvironmentVariable("CSSCRIPT_DIR"); string tempDir = Path.Combine(Path.Combine(Path.GetTempPath(), "CSSCRIPT"), Environment.TickCount.ToString()); string projFile = Path.Combine(tempDir, "DebugScript.prjx"); string solutionFile = Path.Combine(tempDir, "DebugScript.cmbx"); //copy project template Directory.CreateDirectory(tempDir); foreach (string file in Directory.GetFiles(Path.Combine(scHomeDir, srcProjDir))) File.Copy(file, Path.Combine(tempDir, Path.GetFileName(file)), true); //update project template with script specific data SharpDevelopIDE ide = new SharpDevelopIDE(); ScriptParser parser = new ScriptParser(scriptFile, SearchDirs); AssemblyResolver asmResolver = new AssemblyResolver(); ide.InsertFile(scriptFile, projFile); string[] importerdScripts = parser.SaveImportedScripts(); foreach (string file in importerdScripts) ide.InsertFile(file, projFile); System.Diagnostics.Debug.Assert(false); foreach (string name in parser.ReferencedNamespaces) { bool ignore = false; foreach (string ignoreName in parser.IgnoreNamespaces) if (ignore = (name == ignoreName)) break; if (ignore) continue; string[] asmFiles = AssemblyResolver.FindAssembly(name, SearchDirs); foreach (string file in asmFiles) { ide.InsertReference(file, projFile); } } foreach (string asmName in parser.ReferencedAssemblies) //some assemblies were referenced from code { string[] asmFiles = AssemblyResolver.FindAssembly(asmName, SearchDirs); foreach (string file in asmFiles) ide.InsertReference(file, projFile); } //open project Environment.CurrentDirectory = Path.GetDirectoryName(scriptFile); Process myProcess = new Process(); myProcess.StartInfo.FileName = SharpDevelopIDE.GetIDEFile(); myProcess.StartInfo.Arguments = "\"" + solutionFile + "\" "; myProcess.Start(); myProcess.WaitForExit(); //do clean up Directory.Delete(tempDir, true); foreach (string file in importerdScripts) { if (Path.GetFileName(file).StartsWith("i_")) //imported modified files have name "i_file_XXXXXX.cs>" { File.SetAttributes(file, FileAttributes.Normal); File.Delete(file); } } } catch (Exception e) { MessageBox.Show("Specified file could not be linked to the temp project:\n" + e.Message); } } }
/// <summary> /// Compiles C# script file. /// </summary> string Compile(string scriptFileName) { //System.Diagnostics.Debug.Assert(false); bool generateExe = options.buildExecutable; string scriptDir = Path.GetDirectoryName(scriptFileName); string assemblyFileName = ""; //options may be uninitialized in case we are compiling from CSScriptLibrary if (options.searchDirs.Length == 0) options.searchDirs = new string[] { scriptDir }; //parse source file in order to find all referenced assemblies //ASSUMPTION: assembly name is the same as namespace + ".dll" //if script doesn't follow this assumption user will need to //specify assemblies explicitly ScriptParser parser = new ScriptParser(scriptFileName, options.searchDirs); options.searchDirs = Utils.RemoveDuplicates( Utils.Concat( parser.SearchDirs, //parser.searchDirs may be updated as result of script parsing Utils.GetAssemblyDirectoryName(Assembly.GetExecutingAssembly()))); string[] filesToInject = new string[0]; ICodeCompiler compiler = LoadCompiler(scriptFileName, ref filesToInject); CompilerParameters compilerParams = new CompilerParameters(); foreach (string file in parser.Precompilers) if (options.preCompilers == "") options.preCompilers = FileParser.ResolveFile(file, options.searchDirs); else options.preCompilers += "," + FileParser.ResolveFile(file, options.searchDirs); if (options.compilerOptions != string.Empty) Utils.AddCompilerOptions(compilerParams, options.compilerOptions); foreach (string option in parser.CompilerOptions) Utils.AddCompilerOptions(compilerParams, option); if (options.DBG) Utils.AddCompilerOptions(compilerParams, "/d:DEBUG /d:TRACE"); compilerParams.IncludeDebugInformation = options.DBG; compilerParams.GenerateExecutable = generateExe; compilerParams.GenerateInMemory = false; compilerParams.WarningLevel = (options.hideCompilerWarnings ? -1 : 4); string[] filesToCompile = Utils.RemoveDuplicates(parser.FilesToCompile); PrecompilationContext context = CSSUtils.Precompile(scriptFileName, filesToCompile, options); if (context.NewIncludes.Count > 0) { for (int i = 0; i < context.NewIncludes.Count; i++) { context.NewIncludes[i] = FileParser.ResolveFile(context.NewIncludes[i], options.searchDirs); } filesToCompile = Utils.Concat(filesToCompile, context.NewIncludes.ToArray()); context.NewDependencies.AddRange(context.NewIncludes); } string[] additionalDependencies = context.NewDependencies.ToArray(); AddReferencedAssemblies(compilerParams, scriptFileName, parser); //add resources referenced from code foreach (string resFile in parser.ReferencedResources) { string file = null; foreach (string dir in options.searchDirs) { file = Path.IsPathRooted(resFile) ? Path.GetFullPath(resFile) : Path.Combine(dir, resFile); if (File.Exists(file)) break; } if (file == null) file = resFile; Utils.AddCompilerOptions(compilerParams, "\"/res:" + file + "\""); //e.g. /res:C:\\Scripting.Form1.resources"; } if (options.forceOutputAssembly != "") { assemblyFileName = options.forceOutputAssembly; } else { if (generateExe) assemblyFileName = Path.Combine(scriptDir, Path.GetFileNameWithoutExtension(scriptFileName) + ".exe"); else if (options.useCompiled || options.DLLExtension) { if (options.DLLExtension) assemblyFileName = Path.Combine(scriptDir, Path.GetFileNameWithoutExtension(scriptFileName) + ".dll"); else if (options.hideTemp != Settings.HideOptions.DoNotHide) assemblyFileName = Path.Combine(CSExecutor.ScriptCacheDir, Path.GetFileName(scriptFileName) + ".compiled"); else assemblyFileName = scriptFileName + ".compiled"; } else { string tempFile = GetScriptTempFile(); assemblyFileName = Path.ChangeExtension(tempFile, ".dll"); } } if (generateExe && options.buildWinExecutable) Utils.AddCompilerOptions(compilerParams, "/target:winexe"); if (Path.GetExtension(assemblyFileName).ToLower() == ".pdb") { throw new ApplicationException("The specified assembly file name cannot have the reserved extension '.pdb'"); } Utils.FileDelete(assemblyFileName, true); string dbgSymbols = Path.ChangeExtension(assemblyFileName, ".pdb"); if (options.DBG && File.Exists(dbgSymbols)) Utils.FileDelete(dbgSymbols); compilerParams.OutputAssembly = assemblyFileName; string outDir = Path.GetDirectoryName(Path.GetFullPath(compilerParams.OutputAssembly)); if (!Directory.Exists(outDir)) Directory.CreateDirectory(outDir); //compilerParams.ReferencedAssemblies.Add(this.GetType().Assembly.Location); CompilerResults results; if (generateExe) { results = CompileAssembly(compiler, compilerParams, filesToCompile); } else { if (filesToInject.Length != 0) { filesToCompile = Utils.Concat(filesToCompile, filesToInject); } CSSUtils.VerbosePrint(" Output file: \n " + assemblyFileName, options); CSSUtils.VerbosePrint("", options); CSSUtils.VerbosePrint(" Files to compile: ", options); int i = 0; foreach (string file in filesToCompile) CSSUtils.VerbosePrint(" " + i++ + " - " + file, options); CSSUtils.VerbosePrint("", options); CSSUtils.VerbosePrint(" References: ", options); i = 0; foreach (string file in compilerParams.ReferencedAssemblies) CSSUtils.VerbosePrint(" " + i++ + " - " + file, options); CSSUtils.VerbosePrint("> ----------------", options); string originalExtension = Path.GetExtension(compilerParams.OutputAssembly); if (originalExtension != ".dll") { //Despite the usage of .dll file name is not required for MS C# compiler we need to do this because //some compilers (Mono, VB) accept only dll or exe file extensions. compilerParams.OutputAssembly = Path.ChangeExtension(compilerParams.OutputAssembly, ".dll"); Utils.FileDelete(compilerParams.OutputAssembly, true); results = CompileAssembly(compiler, compilerParams, filesToCompile); if (File.Exists(compilerParams.OutputAssembly)) { int attempts = 0; while (true) { //There were reports of MS C# compiler (csc.exe) not releasing OutputAssembly file //after compilation finished. Thus wait a little... //BTW. on Mono 1.2.4 it happens all the time try { attempts++; File.Move(compilerParams.OutputAssembly, Path.ChangeExtension(compilerParams.OutputAssembly, originalExtension)); break; } catch { if (attempts > 2) { //yep we can get here as Mono 1.2.4 on Windows never ever releases the assembly File.Copy(compilerParams.OutputAssembly, Path.ChangeExtension(compilerParams.OutputAssembly, originalExtension), true); break; } else Thread.Sleep(100); } } } } else { Utils.FileDelete(compilerParams.OutputAssembly, true); results = CompileAssembly(compiler, compilerParams, filesToCompile); } } if (options.syntaxCheck && File.Exists(compilerParams.OutputAssembly)) Utils.FileDelete(compilerParams.OutputAssembly, false); ProcessCompilingResult(results, compilerParams, parser, scriptFileName, assemblyFileName, additionalDependencies); if (options.useSurrogateHostingProcess) { new ScriptLauncherBuilder().BuildSurrogateLauncher(assemblyFileName, options.TargetFramework, compilerParams, options.apartmentState, options.consoleEncoding); } return assemblyFileName; }
internal string[] AggregateReferencedAssemblies(ScriptParser parser) { UniqueAssemblyLocations requestedRefAsms = new UniqueAssemblyLocations(); #if net1 ArrayList refAssemblies = new ArrayList(); #else List<string> refAssemblies = new List<string>(); #endif if (options.shareHostRefAssemblies) foreach (Assembly asm in AppDomain.CurrentDomain.GetAssemblies()) { try { if (CSSUtils.IsDynamic(asm)) continue; if (!File.Exists(asm.Location) || asm.Location.Contains("mscorlib")) continue; requestedRefAsms.AddAssembly(asm.Location); } catch { //Under ASP.NET some assemblies do not have location (e.g. dynamically built/emitted assemblies) //in such case NotSupportedException will be raised //In fact ignore all exceptions as we should continue if for whatever reason assembly the location cannot be obtained } } //add assemblies referenced from command line string[] cmdLineAsms = options.refAssemblies; if (!options.useSurrogateHostingProcess) { string[] defaultAsms = options.defaultRefAssemblies.Replace(" ", "").Split(";,".ToCharArray()); foreach (string asmName in Utils.Concat(defaultAsms, cmdLineAsms)) { if (asmName == "") continue; string[] files = AssemblyResolver.FindAssembly(asmName, options.searchDirs); if (files.Length > 0) { foreach (string asm in files) requestedRefAsms.AddAssembly(NormalizeGacAssemblyPath(asm)); } else { requestedRefAsms.AddAssembly(asmName); } } } AssemblyResolver.ignoreFileName = Path.GetFileNameWithoutExtension(parser.ScriptPath) + ".dll"; //add assemblies referenced from code foreach (string asmName in parser.ResolvePackages()) requestedRefAsms.AddAssembly(asmName); //add assemblies referenced from code foreach (string asmName in parser.ReferencedAssemblies) { string asm = asmName.Replace("\"", ""); if (Path.IsPathRooted(asm)) //absolute path { //not-searchable assemblies if (File.Exists(asm)) requestedRefAsms.AddAssembly(NormalizeGacAssemblyPath(asm)); } else { string[] files = AssemblyResolver.FindAssembly(asm, options.searchDirs); if (files.Length > 0) { foreach (string asmFile in files) requestedRefAsms.AddAssembly(NormalizeGacAssemblyPath(asmFile)); } else { requestedRefAsms.AddAssembly(asm); } } } bool disableNamespaceResolving = false; if (parser.IgnoreNamespaces.Length == 1 && parser.IgnoreNamespaces[0] == "*") disableNamespaceResolving = true; if (!disableNamespaceResolving) { //add local and global assemblies (if found) that have the same assembly name as a namespace foreach (string nmSpace in parser.ReferencedNamespaces) { bool ignore = false; //user may nominate namespaces to be excluded fro namespace-to-asm resolving foreach (string ignoreNamespace in parser.IgnoreNamespaces) if (ignoreNamespace == nmSpace) ignore = true; if (!ignore) { bool alreadyFound = requestedRefAsms.ContainsAssembly(nmSpace); if (!alreadyFound) foreach (string asm in AssemblyResolver.FindAssembly(nmSpace, options.searchDirs)) requestedRefAsms.AddAssembly(NormalizeGacAssemblyPath(asm)); } } } return (string[]) requestedRefAsms; }
void AddReferencedAssemblies(CompilerParameters compilerParams, string scriptFileName, ScriptParser parser) { //scriptFileName is obsolete as it is now can be obtained from parser (ScriptParser.ScriptPath) string[] asms = AggregateReferencedAssemblies(parser); compilerParams.ReferencedAssemblies.AddRange(asms); }
/// <summary> /// Compiles C# script file. /// </summary> private string Compile(string scriptFileName) { bool generateExe = options.buildExecutable; string scriptDir = Path.GetDirectoryName(scriptFileName); string assemblyFileName = ""; string tempDir = Path.GetDirectoryName(GetScriptTempFile()); //options may be uninitialized in case we are compileng from CSScriptLibrary if (options.searchDirs.Length == 0) options.searchDirs = new string[]{scriptDir}; //parse source file in order to find all referenced assemblies //ASSUMPTION: assembly name is the same as namespace + ".dll" //if script doesn't follow this assumption user will need to //specify assemblies explicitly ScriptParser parser = new ScriptParser(scriptFileName, options.searchDirs); ICodeCompiler compiler; if (options.altCompiler == "") { compiler = (new CSharpCodeProvider()).CreateCompiler(); } else { try { Assembly asm = Assembly.LoadFrom(Path.IsPathRooted(options.altCompiler) ? options.altCompiler : Path.Combine(Path.GetDirectoryName(Application.ExecutablePath), options.altCompiler)); Type[] types = asm.GetModules()[0].FindTypes(Module.FilterTypeName, "CSSCodeProvider"); MethodInfo method = types[0].GetMethod("CreateCompiler"); compiler = (ICodeCompiler)method.Invoke(null, new object[]{scriptFileName}); } catch (Exception ex) { throw new Exception("Cannot use alternative compiler", ex); } } CompilerParameters compileParams = new CompilerParameters(); if (options.DBG) compileParams.CompilerOptions = "/d:DEBUG /d:TRACE "; if (options.compilerOptions != string.Empty) compileParams.CompilerOptions += options.compilerOptions; compileParams.IncludeDebugInformation = options.DBG; compileParams.GenerateExecutable = generateExe; compileParams.GenerateInMemory = !generateExe; ArrayList refAssemblies = new ArrayList(); //add assemblies were referenced from command line foreach (string asmName in options.refAssemblies) compileParams.ReferencedAssemblies.AddRange(AssemblyResolver.FindAssembly(asmName, options.searchDirs)); AssemblyResolver.ignoreFileName = Path.GetFileNameWithoutExtension(scriptFileName) + ".dll"; //add local and global assemblies (if found) that have the same assembly name as a namespace foreach (string nmSpace in parser.ReferencedNamespaces) compileParams.ReferencedAssemblies.AddRange(AssemblyResolver.FindAssembly(nmSpace, options.searchDirs)); //add assemblies referenced from code foreach (string asmName in parser.ReferencedAssemblies) if (asmName.StartsWith("\"") && asmName.EndsWith("\"")) compileParams.ReferencedAssemblies.Add(asmName.Replace("\"", "")); //not-searchable assemblies else compileParams.ReferencedAssemblies.AddRange(AssemblyResolver.FindAssembly(asmName, options.searchDirs)); //add resources referenced from code foreach (string resFile in parser.ReferencedResources) { string file = null; foreach (string dir in options.searchDirs) { file = Path.IsPathRooted(resFile) ? Path.GetFullPath(resFile) : Path.Combine(dir, resFile); if (File.Exists(file)) break; } if (file == null) file = resFile; compileParams.CompilerOptions += "\"/res:" + file + "\" "; //eg. /res:C:\\Scripting.Form1.resources"; } if (options.forceOutputAssembly != "") { assemblyFileName = options.forceOutputAssembly; } else { if (generateExe) assemblyFileName = Path.Combine(scriptDir, Path.GetFileNameWithoutExtension(scriptFileName) + ".exe"); else if (options.useCompiled || options.DLLExtension) { if (options.DLLExtension) assemblyFileName = Path.Combine(scriptDir, Path.GetFileNameWithoutExtension(scriptFileName) + ".dll"); else if (options.hideTemp != Settings.HideOptions.DoNotHide) assemblyFileName = Path.Combine(CSExecutor.ScriptCacheDir, Path.GetFileName(scriptFileName) + "c"); else assemblyFileName = scriptFileName + "c"; } else { string tempFile = Path.GetTempFileName(); if (File.Exists(tempFile)) File.Delete(tempFile); assemblyFileName = Path.Combine(tempDir, Path.GetFileNameWithoutExtension(tempFile)+".dll"); } } if (generateExe && options.buildWinExecutable) compileParams.CompilerOptions += "/target:winexe "; if (File.Exists(assemblyFileName)) File.Delete(assemblyFileName); compileParams.OutputAssembly = assemblyFileName; CompilerResults results; if (generateExe) { results = compiler.CompileAssemblyFromFileBatch(compileParams, parser.FilesToCompile); } else { string originalExtension = Path.GetExtension(compileParams.OutputAssembly); if (originalExtension != ".dll") { //Despite the usage of .dll file name is not required for MS C# compiler we need to do this because //some compilers (Mono, VB) accept only dll or exe file extensions. compileParams.OutputAssembly = Path.ChangeExtension(compileParams.OutputAssembly, ".dll"); if (File.Exists(compileParams.OutputAssembly)) File.Delete(compileParams.OutputAssembly); results = compiler.CompileAssemblyFromFileBatch(compileParams, parser.FilesToCompile); if (File.Exists(compileParams.OutputAssembly)) { while (true) { //There were reports of MS C# compiler (csc.exe) notr releasing OutputAssembly file //after compilation finished. Thus wait a little... try { using (File.Open(compileParams.OutputAssembly, FileMode.Open, FileAccess.Read, FileShare.None)) break; } catch { Thread.Sleep(100); } } File.Move(compileParams.OutputAssembly, Path.ChangeExtension(compileParams.OutputAssembly, originalExtension)); } } else { if (File.Exists(compileParams.OutputAssembly)) File.Delete(compileParams.OutputAssembly); results = compiler.CompileAssemblyFromFileBatch(compileParams, parser.FilesToCompile); } } if (results.Errors.Count != 0) { StringBuilder compileErr = new StringBuilder(); foreach (CompilerError err in results.Errors) { if (err.IsWarning && options.hideCompilerWarnings) continue; compileErr.Append(err.ToString()); compileErr.Append(Environment.NewLine); compileErr.Append(Environment.NewLine); } throw new Exception(compileErr.ToString()); } else { if (!options.DBG) //.pdb and imported files might be needed for the debugger { parser.DeleteImportedFiles(); string pdbFile = Path.Combine(Path.GetDirectoryName(assemblyFileName), Path.GetFileNameWithoutExtension(assemblyFileName)+".pdb"); if (File.Exists(pdbFile)) File.Delete(pdbFile); } if (options.useCompiled) { if (options.useSmartCaching) { MetaDataItems depInfo = new MetaDataItems(); //save referenced local assemblies info foreach(string assembly in compileParams.ReferencedAssemblies) { foreach(string dir in options.searchDirs) if (string.Compare(dir, Path.GetDirectoryName(assembly), true) == 0) { FileInfo assemblyInfo = new FileInfo(assembly); depInfo.AddItem(Path.GetFileName(assembly), assemblyInfo.LastWriteTimeUtc, true); break; } } //save imported scripts info foreach(string script in parser.ImportedFiles) { FileInfo scriptInfo = new FileInfo(script); bool local = false; foreach (string dir in options.searchDirs) if ((local = (string.Compare(dir, Path.GetDirectoryName(scriptInfo.FullName), true) == 0))) break; if (local) depInfo.AddItem(Path.GetFileName(script), scriptInfo.LastWriteTimeUtc, false); else depInfo.AddItem(script, scriptInfo.LastWriteTimeUtc, false); } depInfo.StampFile(assemblyFileName); } FileInfo scriptFile = new FileInfo(scriptFileName); FileInfo asmFile = new FileInfo(assemblyFileName); if (scriptFile!= null && asmFile != null) { //Console.WriteLine("Update LastWriteTime"+assemblyFileName); //temp os asmFile.LastWriteTime = scriptFile.LastWriteTime; asmFile.LastWriteTimeUtc = scriptFile.LastWriteTimeUtc; } } } return assemblyFileName; }
private void ProcessCompilingResult(CompilerResults results, CompilerParameters compilerParams, ScriptParser parser, string scriptFileName, string assemblyFileName, string[] additionalDependencies) { LastCompileResult = results; if (results.Errors.Count != 0) { throw CompilerException.Create(results.Errors, options.hideCompilerWarnings); } else { if (!options.DBG) //.pdb and imported files might be needed for the debugger { parser.DeleteImportedFiles(); string pdbFile = Path.Combine(Path.GetDirectoryName(assemblyFileName), Path.GetFileNameWithoutExtension(assemblyFileName) + ".pdb"); if (File.Exists(pdbFile)) File.Delete(pdbFile); } if (options.useCompiled) { if (options.useSmartCaching) { MetaDataItems depInfo = new MetaDataItems(); string[] searchDirs = Utils.RemovePathDuplicates(options.searchDirs); //save imported scripts info depInfo.AddItems(parser.ImportedFiles, false, searchDirs); //additionalDependencies (precompilers) are warranted to be as absolute path so no need to pass searchDirs or isAssembly depInfo.AddItems(additionalDependencies, false, new string[0]); //save referenced local assemblies info string[] newProbingDirs = depInfo.AddItems(compilerParams.ReferencedAssemblies, true, searchDirs); foreach (string dir in newProbingDirs) options.AddSearchDir(dir); //needed to be added at Compilation for further resolving during the Invoking stage depInfo.StampFile(assemblyFileName); } FileInfo scriptFile = new FileInfo(scriptFileName); FileInfo asmFile = new FileInfo(assemblyFileName); if (scriptFile != null && asmFile != null) { asmFile.LastWriteTimeUtc = scriptFile.LastWriteTimeUtc; } } } }