/// <summary> /// Execute the task /// </summary> /// <returns>true if task succeeded, false otherwise</returns> public void Execute() { if (!runningFromCommandLine) { string arguments = Parser.Arguments; Output.Message(MessageImportance.Low, Parser.CommandName + (arguments.Length == 0 ? "" : " " + Parser.Arguments)); } // If the help option appears anywhere, just show the help if (this.ShowHelp) { Output.Message(Parser.LogoBanner); Output.Message(Parser.Usage); Output.Message(""); return; } // From this point on assume a bad exit code this.ExitCode = 1; // At this point, we need a source file (the default argument) if (this.ScriptPath == null) { Output.Error(CsrResources.NoScriptSpecified); return; } // Need a zero length array if no command line arguments given if (this.Arguments == null) { this.Arguments = new string[0]; } // Before we fully qualify the file record whether it had any full or relative path part bool justFilenameGiven = this.ScriptPath.IsFilenameOnly; if (this.ScriptPath.File == String.Empty) { Output.Error(CsrResources.NoEmptyFileName); return; } else if (this.ScriptPath.HasWildcards) { Output.Error(CsrResources.NoScriptWildcards); return; } if (this.ScriptPath.Extension == String.Empty) { this.ScriptPath = new ParsedPath(this.ScriptPath.VolumeDirectoryAndFile + ".csr", PathType.File); } // Fully qualify the path based on current directory this.ScriptPath = this.ScriptPath.MakeFullPath(); // Check that the source exists, and optionally search for it in the PATH if (!File.Exists(this.ScriptPath)) { if (this.SearchSystemPath && justFilenameGiven) { IList <ParsedPath> found = PathUtility.FindFileInPaths( new ParsedPathList(System.Environment.GetEnvironmentVariable("PATH"), PathType.Directory), this.ScriptPath.FileAndExtension); if (found.Count > 0) { this.ScriptPath = new ParsedPath(found[0], PathType.File); if (this.DebugMessages) { Output.Message(MessageImportance.Low, CsrResources.ScriptFoundInPath(this.ScriptPath.FileAndExtension, this.ScriptPath.VolumeAndDirectory)); } } else { Output.Error(CsrResources.ScriptNotFoundInDirectoryOrPath(this.ScriptPath.FileAndExtension, this.ScriptPath.VolumeAndDirectory)); return; } } else { Output.Error(CsrResources.ScriptNotFound(this.ScriptPath)); return; } } // Set publicly visible script path (in this AppDomain) ScriptEnvironment.ScriptPath = this.ScriptPath; // Now we have a valid script file, go an extract the details ScriptInfo scriptInfo = null; try { scriptInfo = ScriptInfo.GetScriptInfo(this.ScriptPath); } catch (ScriptInfoException e) { Output.Error(e.Message); return; } IList <RuntimeInfo> runtimeInfos = RuntimeInfo.GetInstalledRuntimes(); RuntimeInfo runtimeInfo = null; // Check to see that the scripts requested CLR & Fx are available. for (int i = 0; i < runtimeInfos.Count; i++) { if (runtimeInfos[i].ClrVersion == scriptInfo.ClrVersion && runtimeInfos[i].FxVersion == scriptInfo.FxVersion) { runtimeInfo = runtimeInfos[i]; break; } } if (runtimeInfo == null) { Output.Error(CsrResources.ScriptsRequiredRuntimeAndFrameworkNotInstalled(scriptInfo.ClrVersion, scriptInfo.FxVersion)); return; } IList <ParsedPath> references; try { references = ScriptInfo.GetFullScriptReferencesPaths(scriptPath, scriptInfo, runtimeInfo); } catch (ScriptInfoException e) { Output.Error(e.Message); return; } if (this.DebugMessages) { Output.Message(MessageImportance.Low, CsrResources.RuntimeVersion( ProcessUtility.IsThis64BitProcess ? CsrResources.WordSize64 : CsrResources.WordSize32, RuntimeEnvironment.GetSystemVersion().ToString())); Output.Message(MessageImportance.Low, CsrResources.ClrInstallPath(runtimeInfo.ClrInstallPath)); Output.Message(MessageImportance.Low, CsrResources.NetFxInstallPath(runtimeInfo.FxInstallPath)); Output.Message(MessageImportance.Low, CsrResources.NetFxReferenceAssemblyPath(runtimeInfo.FxReferenceAssemblyPath)); Output.Message(MessageImportance.Low, CsrResources.TemporaryFileDirectory(TemporaryFileDirectory)); foreach (var reference in references) { Output.Message(MessageImportance.Low, CsrResources.Referencing(reference)); } } try { IDictionary <string, string> providerOptions = new Dictionary <string, string>(); // Setting the compiler version option should only be done under Fx 3.5 otherwise the option should be not present if (scriptInfo.FxVersion == "3.5") { providerOptions.Add("CompilerVersion", "v" + scriptInfo.FxVersion); } CodeDomProvider provider = new CSharpCodeProvider(providerOptions); CompilerParameters parms = new CompilerParameters(); // NOTE: When adding compiler options, don't forget to always add a space at end... <sigh/> StringBuilder compilerOptions = new StringBuilder(); foreach (var reference in references) { compilerOptions.AppendFormat("/r:\"{0}\" ", reference); } parms.CompilerOptions = compilerOptions.ToString(); parms.GenerateExecutable = true; // This doesn't mean generate a file on disk, it means generate an .exe not a .dll if (StackTraces) { if (!Directory.Exists(TemporaryFileDirectory)) { Directory.CreateDirectory(this.TemporaryFileDirectory); } parms.OutputAssembly = TemporaryFileDirectory.VolumeAndDirectory + ScriptPath.File + ".exe"; parms.GenerateInMemory = false; parms.IncludeDebugInformation = true; parms.CompilerOptions += "/optimize- "; } else { parms.GenerateInMemory = true; parms.CompilerOptions += "/optimize+ "; } if (this.AllowUnsafeCode) { parms.CompilerOptions += "/unsafe+ "; } if (DebugMessages) { Output.Message(MessageImportance.Low, "Compiling script file '{0}'", this.ScriptPath); } CompilerResults results = provider.CompileAssemblyFromFile(parms, this.ScriptPath); if (results.Errors.Count > 0) { foreach (CompilerError error in results.Errors) { Console.Error.WriteLine( CsrResources.ErrorLine(error.FileName, error.Line, error.Column, error.ErrorNumber, error.ErrorText)); } return; } else { // Take the compiled assembly and invoke it in this appdomain. object ret = null; ScriptEnvironment.FullyQualifiedReferences = references; AppDomain.CurrentDomain.AssemblyResolve += new ResolveEventHandler(OnAssemblyResolve); // Get information about the entry point MethodInfo mainMethod = results.CompiledAssembly.EntryPoint; ParameterInfo[] mainParams = mainMethod.GetParameters(); Type returnType = mainMethod.ReturnType; try { if (returnType == typeof(void)) { if (mainParams.Length > 0) { mainMethod.Invoke(null, new object[1] { this.Arguments }); } else { mainMethod.Invoke(null, null); } } else { if (mainParams.Length > 0) { ret = mainMethod.Invoke(null, new object[1] { this.Arguments }); } else { ret = mainMethod.Invoke(null, null); } } } catch (Exception ex) // Catch script errors { // When catching a script error here, the actual script exception will be the inner exception Output.Error(String.Format( CsrResources.ExceptionFromScript(ex.InnerException != null ? ex.InnerException.Message : ex.Message))); if (this.StackTraces && ex.InnerException != null) { Output.Error(ex.InnerException.StackTrace); } return; } if (ret != null && returnType == typeof(int)) { this.ExitCode = (int)ret; return; } } } catch (Exception ex) // Catch compilation exceptions { string message = CsrResources.ExceptionDuringCompile + ex.Message; if (ex.InnerException != null) { message += ex.InnerException.Message; } Output.Error(message); return; } ExitCode = 0; return; }
private void RealExecute() { // At this point, we need a program (the default argument) if (this.ScriptPath == null) { Output.Error(ScaffoldResources.NoSourceSpecified); return; } // Fully qualify the program this.ScriptPath = this.ScriptPath.MakeFullPath(); if (this.ScriptPath.File == String.Empty) { Output.Error(ScaffoldResources.NoEmptyFilename); return; } else if (this.ScriptPath.HasWildcards) { Output.Error(ScaffoldResources.NoSourceWildcards); return; } else if (this._Language == ScriptLanguage.Unknown) { Output.Error(ScaffoldResources.FileNameMustEndIn); return; } // TODO-johnls-12/15/2007: More project types coming soon...? if (this._Language != ScriptLanguage.CSharp) { Output.Error(ScaffoldResources.OnlyCSharpSourcesSupported); return; } // Look for installed VS versions get information about them IList <VisualStudioInfo> vsInfos = VisualStudioInfo.GetInstalledVisualStudios(); if (vsInfos.Count == 0) { // Must have at least one supported version of Visual Studio installed Output.Error(ScaffoldResources.VSNotInstalled(StringUtility.Join(", ", ScriptInfo.ValidVisualStudioVersions))); return; } // Get list of installed runtimes. IList <RuntimeInfo> runtimeInfos = RuntimeInfo.GetInstalledRuntimes(); // If VS is installed we have at least one runtime... if (runtimeInfos.Count == 0) { Output.Error(ScaffoldResources.RuntimeNotInstalled(StringUtility.Join(", ", ScriptInfo.ValidRuntimeVersions))); return; } ScriptInfo scriptInfo = null; VisualStudioInfo vsInfo; RuntimeInfo runtimeInfo; if (File.Exists(this.ScriptPath)) { try { // Grab script information from script scriptInfo = ScriptInfo.GetScriptInfo(this.ScriptPath); } catch (ScriptInfoException e) { Output.Error(e.Message); return; } // Validate that VS/CLR/FX versions installed runtimeInfo = ((List <RuntimeInfo>)runtimeInfos).Find( v => (scriptInfo.ClrVersion == v.ClrVersion && scriptInfo.FxVersion == v.FxVersion)); vsInfo = ((List <VisualStudioInfo>)vsInfos).Find( v => (scriptInfo.VsVersion == v.VsVersion)); if (runtimeInfo == null || vsInfo == null) { Output.Error(ScaffoldResources.ScriptsRequiredClrFxAndVsNotInstalled(scriptInfo.ClrVersion, scriptInfo.FxVersion, scriptInfo.VsVersion)); return; } } else { vsInfo = vsInfos[0]; runtimeInfo = runtimeInfos[0]; scriptInfo = new ScriptInfo(vsInfo.VsVersion, runtimeInfo.ClrVersion, runtimeInfo.FxVersion, new List <string>()); // Go grab references from the csc.rsp file and add CodeRunner.dll and ToolBelt.dll // in the same directory as Scaffold.exe. scriptInfo.References.AddRange(GrabSystemRspFileReferences(runtimeInfo.FxInstallPath.Append("csc.rsp", PathType.File), runtimeInfo)); scriptInfo.References.Add(@"$(CodeRunnerPath)CodeRunner.dll"); scriptInfo.References.Add(@"$(CodeRunnerPath)ToolBelt.dll"); } ParsedPath projectDir = CreateTempDirectory(); if (!CreateProjectFiles(scriptInfo, vsInfo, runtimeInfo, projectDir)) { return; } StartDevenvAndWait(vsInfos[0], new ParsedPath( projectDir.VolumeAndDirectory + this.ScriptPath.File + ".sln", PathType.File)); DeleteDirectory(projectDir); }
internal static IList <ParsedPath> GetFullScriptReferencesPaths(ParsedPath scriptPath, ScriptInfo scriptInfo, RuntimeInfo runtimeInfo) { List <ParsedPath> paths = new List <ParsedPath>(); Dictionary <string, string> dict = new Dictionary <string, string>(); dict.Add("FxInstallPath", runtimeInfo.FxInstallPath); dict.Add("FxReferenceAssemblyPath", runtimeInfo.FxReferenceAssemblyPath); dict.Add("ClrInstallPath", runtimeInfo.ClrInstallPath); dict.Add("ScriptPath", scriptPath.VolumeAndDirectory); dict.Add("CodeRunnerPath", new ParsedPath(Process.GetCurrentProcess().MainModule.FileName, PathType.File).VolumeAndDirectory); string reference = String.Empty; try { for (int i = 0; i < scriptInfo.References.Count; i++) { reference = scriptInfo.References[i]; string fullReference = StringUtility.ReplaceTags(reference, "$(", ")", dict); ParsedPath path = new ParsedPath(fullReference, PathType.File).MakeFullPath(scriptPath); paths.Add(path); } } catch (ArgumentException e) { // Could be bad crap in the reference paths throw new ScriptInfoException(CodeRunnerResources.BadReferencePaths(reference, e.Message)); } return(paths); }
private bool CreateProjectFiles(ScriptInfo scriptInfo, VisualStudioInfo vsInfo, RuntimeInfo runtimeInfo, ParsedPath projectDir) { if (!Directory.Exists(this.ScriptPath.VolumeAndDirectory)) { Output.Error(ScaffoldResources.DirectoryDoesNotExist(this.ScriptPath.VolumeAndDirectory)); return(false); } Dictionary <string, string> dict = new Dictionary <string, string>(); dict.Add("AssemblyName", this.ScriptPath.File); dict.Add("SourceDirectory", this.ScriptPath.VolumeAndDirectory); dict.Add("SourceName", this.ScriptPath.FileAndExtension); dict.Add("ProjectGuid", Guid.NewGuid().ToString().ToUpper()); dict.Add("ProjectTypeExt", ScriptEnvironment.GetExtensionFromScaffoldLanguage(this.language)); dict.Add("ProductVersion", String.Format("{0}.{1}", vsInfo.VsVersion, vsInfo.VsBuild)); dict.Add("ToolsVersion", String.Format(" ToolsVersion=\"{0}\" ", scriptInfo.FxVersion)); dict.Add("TargetFrameworkVersion", "v" + scriptInfo.FxVersion); dict.Add("ScriptVsVersion", scriptInfo.VsVersion); dict.Add("ScriptClrVersion", scriptInfo.ClrVersion); dict.Add("ScriptFxVersion", scriptInfo.FxVersion); switch (scriptInfo.VsVersion) { case "10.0": dict.Add("SolutionFileVersion", "11.00"); dict.Add("VSName", "2010"); break; case "9.0": dict.Add("SolutionFileVersion", "10.00"); dict.Add("VSName", "2008"); break; case "8.0": dict.Add("ToolsVersion", ""); dict.Add("SolutionFileVersion", "9.00"); dict.Add("VSName", "2005"); break; } dict.Add("ScriptReferencesComment", CreateCommentSnippetFromReferences(scriptInfo.References)); dict.Add("ReferenceXmlSnippet", CreateXmlSnippetFromReferences(ScriptInfo.GetFullScriptReferencesPaths(scriptPath, scriptInfo, runtimeInfo))); string tagProgramFile = this.ScriptTemplate; if (tagProgramFile == null || !File.Exists(tagProgramFile)) { tagProgramFile = GetResource("CodeRunner.Templates.Template.cs"); } string sourceFile = StringUtility.ReplaceTags(tagProgramFile, "%", "%", dict); string tagCsProjFile = GetResource("CodeRunner.Templates.Template.csproj"); string csProjFile = StringUtility.ReplaceTags(tagCsProjFile, "%", "%", dict); string tagCsProjUserFile = GetResource("CodeRunner.Templates.Template.csproj.user"); string csProjUserFile = StringUtility.ReplaceTags(tagCsProjUserFile, "%", "%", dict); string tagSlnFile = GetResource("CodeRunner.Templates.Template.sln"); string slnFile = StringUtility.ReplaceTags(tagSlnFile, "%", "%", dict); try { if (!File.Exists(this.ScriptPath)) { CreateFile(this.ScriptPath, sourceFile); } CreateFile(projectDir.VolumeAndDirectory + this.ScriptPath.File + ".csproj", csProjFile); CreateFile(projectDir.VolumeAndDirectory + this.ScriptPath.File + ".csproj.user", csProjUserFile); CreateFile(projectDir.VolumeAndDirectory + this.ScriptPath.File + ".sln", slnFile); } catch (IOException exp) { Output.Error("{0}", exp.Message); return(false); } return(true); }