/// <summary> /// The main entry point for the application. /// </summary> public void Execute(string[] args, PrintDelegate printDelg, string primaryScript) { try { print = printDelg != null ? printDelg : new PrintDelegate(VoidPrint); if (args.Length > 0) { #region Parse command-line arguments... //Here we need to separate application arguments from script ones. //Script engine arguments are always followed by script arguments //[appArgs][scriptFile][scriptArgs][//x] #if net1 ArrayList appArgs = new ArrayList(); #else List<string> appArgs = new List<string>(); #endif //The following will also update corresponding "options" members from "settings" data Settings settings = GetPersistedSettings(appArgs); int firstScriptArg = CSSUtils.ParseAppArgs(args, this); if (!options.processFile) return; //no further processing is required (e.g. print help) if (args.Length <= firstScriptArg) { Environment.ExitCode = 1; print("No script file was specified."); return; //no script, no script arguments } //process original command-line arguments if (options.scriptFileName == "") { options.scriptFileName = args[firstScriptArg]; firstScriptArg++; } for (int i = firstScriptArg; i < args.Length; i++) { if (i == args.Length - 1 && string.Compare(args[args.Length - 1], "//x", true, CultureInfo.InvariantCulture) == 0) { options.startDebugger = true; options.DBG = true; } else appArgs.Add(args[i]); } #if net1 scriptArgs = (string[])appArgs.ToArray(typeof(string)); #else scriptArgs = appArgs.ToArray(); #endif //searchDirs[0] is the script file directory. Set it only after //the script file resolved because it can be: // dir defined by the absolute/relative script file path // "%CSSCRIPT_DIR%\lib // settings.SearchDirs // CacheDir #if net1 ArrayList dirs = new ArrayList(); #else List<string> dirs = new List<string>(); #endif using (IDisposable currDir = new CurrentDirGuard()) { if (options.local) Environment.CurrentDirectory = Path.GetDirectoryName(Path.GetFullPath(options.scriptFileName)); foreach (string dir in options.searchDirs) //some directories may be already set from command-line dirs.Add(Path.GetFullPath(dir)); if (settings != null) foreach (string dir in Environment.ExpandEnvironmentVariables(settings.SearchDirs).Split(",;".ToCharArray())) if (dir.Trim() != "") dirs.Add(Path.GetFullPath(dir)); } dirs.Add(Utils.GetAssemblyDirectoryName(this.GetType().Assembly)); #if net1 options.scriptFileName = FileParser.ResolveFile(options.scriptFileName, (string[])dirs.ToArray(typeof(string))); #else options.scriptFileName = FileParser.ResolveFile(options.scriptFileName, dirs.ToArray()); #endif if (primaryScript != null) options.scriptFileNamePrimary = primaryScript; else options.scriptFileNamePrimary = options.scriptFileName; if (CSExecutor.ScriptCacheDir == "") CSExecutor.SetScriptCacheDir(options.scriptFileName); dirs.Insert(0, Path.GetDirectoryName(Path.GetFullPath(options.scriptFileName))); if (settings != null && settings.HideAutoGeneratedFiles != Settings.HideOptions.DoNotHide) dirs.Add(CSExecutor.ScriptCacheDir); #if net1 options.searchDirs = (string[])dirs.ToArray(typeof(string)); #else options.searchDirs = dirs.ToArray(); #endif CSharpParser.CmdScriptInfo[] cmdScripts = new CSharpParser.CmdScriptInfo[0]; //do quick parsing for pre/post scripts, ThreadingModel and embedded script arguments CSharpParser parser = new CSharpParser(options.scriptFileName, true, null, options.searchDirs); if (parser.Inits.Length != 0) options.initContext = parser.Inits[0]; if (parser.HostOptions.Length != 0) { if (Environment.Version.Major >= 4) { foreach (string optionsSet in parser.HostOptions) foreach (string option in optionsSet.Split(' ')) if (option == "/platform:x86") options.compilerOptions += " " + option; else if (option.StartsWith("/version:")) options.TargetFramework = option.Replace("/version:", ""); options.useSurrogateHostingProcess = true; } } //analyses ThreadingModel to use it with execution thread if (File.Exists(options.scriptFileName)) { if (parser.ThreadingModel != ApartmentState.Unknown) options.apartmentState = parser.ThreadingModel; #if net1 ArrayList preScripts = new ArrayList(parser.CmdScripts); foreach (CSharpParser.ImportInfo info in parser.Imports) { try { string file = FileParser.ResolveFile(info.file, options.searchDirs); if (file.IndexOf(".g.cs") == -1) //non auto-generated file preScripts.AddRange(new CSharpParser(file, true, options.searchDirs).CmdScripts); } catch { } //some files may not be generated yet } cmdScripts = (CSharpParser.CmdScriptInfo[])preScripts.ToArray(typeof(CSharpParser.CmdScriptInfo)); #else List<string> newSearchDirs = new List<string>(options.searchDirs); using (IDisposable currDir = new CurrentDirGuard()) { Environment.CurrentDirectory = Path.GetDirectoryName(Path.GetFullPath(options.scriptFileName)); foreach (string dir in parser.ExtraSearchDirs) newSearchDirs.Add(Path.GetFullPath(dir)); foreach (string file in parser.RefAssemblies) { string path = file.Replace("\"", ""); string dir = Path.GetDirectoryName(path); if (dir != "") newSearchDirs.Add(Path.GetFullPath(dir)); } options.searchDirs = newSearchDirs.ToArray(); } List<CSharpParser.CmdScriptInfo> preScripts = new List<CSharpParser.CmdScriptInfo>(parser.CmdScripts); foreach (CSharpParser.ImportInfo info in parser.Imports) { try { string[] files = FileParser.ResolveFiles(info.file, options.searchDirs); foreach (string file in files) if (file.IndexOf(".g.cs") == -1) //non auto-generated file { using (IDisposable currDir = new CurrentDirGuard()) { CSharpParser impParser = new CSharpParser(file, true, null, options.searchDirs); Environment.CurrentDirectory = Path.GetDirectoryName(file); string[] packageAsms = NuGet.Resolve(impParser.NuGets, true, file); foreach (string asmName in packageAsms) { var packageDir = Path.GetDirectoryName(asmName); newSearchDirs.Add(packageDir); } foreach (string dir in impParser.ExtraSearchDirs) newSearchDirs.Add(Path.GetFullPath(dir)); options.searchDirs = newSearchDirs.ToArray(); } preScripts.AddRange(new CSharpParser(file, true, null, options.searchDirs).CmdScripts); } } catch { } //some files may not be generated yet } cmdScripts = preScripts.ToArray(); #endif if (primaryScript == null)//this is a primary script { int firstEmbeddedScriptArg = CSSUtils.ParseAppArgs(parser.Args, this); if (firstEmbeddedScriptArg != -1) { for (int i = firstEmbeddedScriptArg; i < parser.Args.Length; i++) appArgs.Add(parser.Args[i]); } #if net1 scriptArgs = (string[])appArgs.ToArray(typeof(string)); #else scriptArgs = appArgs.ToArray(); #endif } } #endregion Parse command-line arguments... ExecuteOptions originalOptions = (ExecuteOptions) options.Clone(); //preserve master script options string originalCurrDir = Environment.CurrentDirectory; //run prescripts //Note: during the secondary script execution static options will be modified (this is required for //browsing in CSSEnvironment with reflection). So reset it back with originalOptions after the execution is completed foreach (CSharpParser.CmdScriptInfo info in cmdScripts) if (info.preScript) { Environment.CurrentDirectory = originalCurrDir; info.args[1] = FileParser.ResolveFile(info.args[1], originalOptions.searchDirs); CSExecutor exec = new CSExecutor(info.abortOnError, originalOptions); if (originalOptions.DBG) { #if net1 ArrayList newArgs = new ArrayList(); newArgs.AddRange(info.args); newArgs.Insert(0, CSSUtils.Args.DefaultPrefix + "dbg"); info.args = (string[])newArgs.ToArray(typeof(string)); #else List<string> newArgs = new List<string>(); newArgs.AddRange(info.args); newArgs.Insert(0, CSSUtils.Args.DefaultPrefix + "dbg"); info.args = newArgs.ToArray(); #endif } if (originalOptions.verbose) { #if net1 ArrayList newArgs = new ArrayList(); newArgs.AddRange(info.args); newArgs.Insert(0, CSSUtils.Args.DefaultPrefix + "verbose"); info.args = (string[])newArgs.ToArray(typeof(string)); #else List<string> newArgs = new List<string>(); newArgs.AddRange(info.args); newArgs.Insert(0, CSSUtils.Args.DefaultPrefix + "verbose"); info.args = newArgs.ToArray(); #endif } if (info.abortOnError) exec.Execute(info.args, printDelg, originalOptions.scriptFileName); else exec.Execute(info.args, null, originalOptions.scriptFileName); } options = originalOptions; ExecuteOptions.options = originalOptions; //update static members as well Environment.CurrentDirectory = originalCurrDir; options.compilationContext = CSSUtils.GenerateCompilationContext(parser, options); //Run main script //We need to start the execution in a new thread as it is the only way //to set desired ApartmentState under .NET 2.0 Thread newThread = new Thread(new ThreadStart(this.ExecuteImpl)); #if net1 newThread.ApartmentState = options.apartmentState; #else newThread.SetApartmentState(options.apartmentState); #endif newThread.Start(); newThread.Join(); if (lastException != null) if (lastException is SurrogateHostProcessRequiredException) throw lastException; else throw new ApplicationException("Script " + options.scriptFileName + " cannot be executed.", lastException); //run postscripts foreach (CSharpParser.CmdScriptInfo info in cmdScripts) if (!info.preScript) { Environment.CurrentDirectory = originalCurrDir; info.args[1] = FileParser.ResolveFile(info.args[1], originalOptions.searchDirs); CSExecutor exec = new CSExecutor(info.abortOnError, originalOptions); if (originalOptions.DBG) { #if net1 ArrayList newArgs = new ArrayList(); newArgs.AddRange(info.args); newArgs.Insert(0, CSSUtils.Args.DefaultPrefix + "dbg"); info.args = (string[])newArgs.ToArray(typeof(string)); #else List<string> newArgs = new List<string>(); newArgs.AddRange(info.args); newArgs.Insert(0, CSSUtils.Args.DefaultPrefix + "dbg"); info.args = newArgs.ToArray(); #endif } if (originalOptions.verbose) { #if net1 ArrayList newArgs = new ArrayList(); newArgs.AddRange(info.args); newArgs.Insert(0, CSSUtils.Args.DefaultPrefix + "verbose"); info.args = (string[])newArgs.ToArray(typeof(string)); #else List<string> newArgs = new List<string>(); newArgs.AddRange(info.args); newArgs.Insert(0, CSSUtils.Args.DefaultPrefix + "verbose"); info.args = newArgs.ToArray(); #endif } if (info.abortOnError) { exec.Rethrow = true; exec.Execute(info.args, printDelg, originalOptions.scriptFileName); } else exec.Execute(info.args, null, originalOptions.scriptFileName); } } else { ShowHelp(); } } catch (Surrogate86ProcessRequiredException) { throw; } catch (SurrogateHostProcessRequiredException) { throw; } catch (Exception e) { Exception ex = e; if (e is System.Reflection.TargetInvocationException) ex = e.InnerException; if (rethrow) { throw ex; } else { Environment.ExitCode = 1; if (!CSSUtils.IsRuntimeErrorReportingSupressed) { if (options.reportDetailedErrorInfo && !(ex is FileNotFoundException)) print(ex.ToString()); else print(ex.Message); //Mono friendly } } } }
/// <summary> /// The main entry point for the application. /// </summary> public void Execute(string[] args, PrintDelegate printDelg, string primaryScript) { try { print = printDelg != null ? printDelg : new PrintDelegate(VoidPrint); if (args.Length > 0) { #region Parse command-line arguments... //Here we need to separate application arguments from script ones. //Script engine arguments are always followed by script arguments //[appArgs][scriptFile][scriptArgs][//x] ArrayList appArgs = new ArrayList(); int firstScriptArg = ParseAppArgs(args); if (args.Length <= firstScriptArg) { Environment.ExitCode = 1; return; //no script, no script arguments } //read persistent settings from configuration file Settings settings = null; if (options.noConfig) { if (options.altConfig != "") settings = Settings.Load(Path.GetFullPath(options.altConfig)); } else settings = Settings.Load(Path.Combine(Path.GetDirectoryName(Application.ExecutablePath), "css_config.xml")); if (settings != null) { options.hideTemp = settings.HideAutoGeneratedFiles; options.altCompiler = settings.ExpandUseAlternativeCompiler(); options.apartmentState = settings.DefaultApartmentState; options.reportDetailedErrorInfo = settings.ReportDetailedErrorInfo; options.cleanupShellCommand = settings.ExpandCleanupShellCommand(); options.doCleanupAfterNumberOfRuns = settings.DoCleanupAfterNumberOfRuns; options.hideCompilerWarnings = settings.HideCompilerWarnings; //process default command-line arguments string[] defaultCmdArgs = settings.DefaultArguments.Split(" ".ToCharArray()); int firstDefaultScriptArg = ParseAppArgs(defaultCmdArgs); if (firstDefaultScriptArg != defaultCmdArgs.Length) { options.scriptFileName = defaultCmdArgs[firstDefaultScriptArg]; for (int i = firstDefaultScriptArg+1; i < defaultCmdArgs.Length; i++) if (defaultCmdArgs[i].Trim().Length != 0) appArgs.Add(defaultCmdArgs[i]); } } //process original command-line arguments if (options.scriptFileName == "") { options.scriptFileName = args[firstScriptArg]; firstScriptArg++; } for (int i = firstScriptArg; i < args.Length; i++) { if (args[i].Trim().Length != 0) { if (i == args.Length - 1 && string.Compare(args[args.Length - 1], "//x", true, CultureInfo.InvariantCulture) == 0) { options.startDebugger = true; options.DBG = true; } else appArgs.Add(args[i]); } } scriptArgs = (string[])appArgs.ToArray(typeof(string)); //searchDirs[0] is the script file directory. Set it only after //the script file resolved because it can be: // CurrentDir // dir defined by the absolute/ralative script file path // %CSSCRIPT_DIR% // ExtraLibDirectory // CacheDir options.searchDirs = new string[]{ "", Environment.ExpandEnvironmentVariables(@"%CSSCRIPT_DIR%\lib"), settings == null ? "" : settings.ExpandExtraLibDirectory(), ""}; options.scriptFileName = FileParser.ResolveFile(options.scriptFileName, options.searchDirs); if (primaryScript != null) options.scriptFileNamePrimary = primaryScript; else options.scriptFileNamePrimary = options.scriptFileName; if (CSExecutor.ScriptCacheDir == "") CSExecutor.SetScriptCacheDir(options.scriptFileName); options.searchDirs[0] = Path.GetDirectoryName(Path.GetFullPath(options.scriptFileName)); if (settings != null && settings.HideAutoGeneratedFiles != Settings.HideOptions.DoNotHide) options.searchDirs[3] = CSExecutor.ScriptCacheDir; CSharpParser.CmdScriptInfo[] cmdScripts = new CSharpParser.CmdScriptInfo[0]; //analyse ThreadingModel to use it whith execution thread if (File.Exists(options.scriptFileName)) { //do quick parsing for pre/post scripts, ThreadingModel and embedded script arguments CSharpParser parser = new CSharpParser(options.scriptFileName, true); if (parser.ThreadingModel != ApartmentState.Unknown) options.apartmentState = parser.ThreadingModel; cmdScripts = parser.CmdScripts; if (primaryScript == null)//this is a primary script { int firstEmbeddedScriptArg = ParseAppArgs(parser.Args); if (firstEmbeddedScriptArg != -1) { for (int i = firstEmbeddedScriptArg; i < parser.Args.Length; i++ ) appArgs.Add(parser.Args[i]); } scriptArgs = (string[])appArgs.ToArray(typeof(string)); } } #endregion ExecuteOptions originalOptions = (ExecuteOptions)options.Clone(); //preserve master script options string originalCurrDir = Environment.CurrentDirectory; //run prescripts //Note: during the secondary script execution static options will be modified (this is required for //browsing in CSSEnvironment with reflection). So reset it back with originalOptions after the execution is completed foreach (CSharpParser.CmdScriptInfo info in cmdScripts) if (info.preScript) { Environment.CurrentDirectory = originalCurrDir; info.args[1] = FileParser.ResolveFile(info.args[1], originalOptions.searchDirs); CSExecutor exec = new CSExecutor(info.abortOnError, originalOptions); if (originalOptions.DBG) { ArrayList newArgs = new ArrayList(); newArgs.AddRange(info.args); newArgs.Insert(0, "/dbg"); info.args = (string[])newArgs.ToArray(typeof(string)); } if (info.abortOnError) exec.Execute(info.args, printDelg, originalOptions.scriptFileName); else exec.Execute(info.args, null, originalOptions.scriptFileName); } options = originalOptions; ExecuteOptions.options = originalOptions; //update static members as well Environment.CurrentDirectory = originalCurrDir; //Run main script //We need to start the execution in a new thread as it is the only way //to set desired ApartmentState under .NET 2.0 Thread newThread = new Thread(new ThreadStart(this.ExecuteImpl)); newThread.ApartmentState = options.apartmentState; newThread.Start(); newThread.Join(); if (lastException != null) throw new Exception("Script "+options.scriptFileName+" cannot be executed.", lastException); //run postscripts foreach (CSharpParser.CmdScriptInfo info in cmdScripts) if (!info.preScript) { Environment.CurrentDirectory = originalCurrDir; info.args[1] = FileParser.ResolveFile(info.args[1], originalOptions.searchDirs); CSExecutor exec = new CSExecutor(info.abortOnError, originalOptions); if (originalOptions.DBG) { ArrayList newArgs = new ArrayList(); newArgs.AddRange(info.args); newArgs.Insert(0, "/dbg"); info.args = (string[])newArgs.ToArray(typeof(string)); } if (info.abortOnError) { exec.Rethrow = true; exec.Execute(info.args, printDelg, originalOptions.scriptFileName); } else exec.Execute(info.args, null, originalOptions.scriptFileName); } } else { ShowHelp(); } } catch (Exception e) { if (rethrow) { throw; } else { Environment.ExitCode = 1; if (options.reportDetailedErrorInfo) print(e.ToString()); else print(e.Message); //Mono friendly } } }