예제 #1
0
        /// <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;
        }
예제 #2
0
        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);
        }
예제 #3
0
        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);
        }
예제 #4
0
        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);
        }