Пример #1
0
        string RunScript(string source, bool execute)
        {
            CompilerResults results;

            using (var provider = new IACodeProvider())
            {
                var options = new IACompilerParameters { GenerateExecutable = false, GenerateInMemory = true, Merge = true, MergeFallbackToLink = true };
                results = provider.CompileAssemblyFromFile(options, source);
            }

            var buffer = new StringBuilder();

            using (var writer = new StringWriter(buffer))
            {
                Console.SetOut(writer);

                if (execute)
                    results.CompiledAssembly.EntryPoint.Invoke(null, null);

                writer.Flush();
            }

            string output = buffer.ToString();

            using (var console = Console.OpenStandardOutput())
            {
                var stdout = new StreamWriter(console);
                stdout.AutoFlush = true;
                Console.SetOut(stdout);
            }

            return output;
        }
Пример #2
0
        private static int Main(string[] args)
        {
            Start(ref args);

            #region Constants

            const int ExitInvalidFunction = 1;
            const int ExitFileNotFound = 2;

            const string ErrorNoPaths = "No source path specified.";
            const string ErrorSourceFileNotFound = "Specified file path not found.";
            const string ErrorDuplicatePaths = "Duplicate paths to source file.";
            const string ErrorOutputUnspecified = "No output path specified.";
            const string ErrorUnrecognisedSwitch = "Unrecognised switch.";
            const string ErrorErrorsOccurred = "The following errors occurred:";
            const string ErrorCompilationFailed = "Compilation failed.";

            #endregion Constants

            #region Command line

            var asm = Assembly.GetExecutingAssembly();
            string self = asm.Location;
            var name = typeof(Program).Namespace;
            string script = null;
            string exe = null;
            gui = Environment.OSVersion.Platform == PlatformID.Unix || Environment.OSVersion.Platform == PlatformID.MacOSX ? false : true;

            for (int i = 0; i < args.Length; i++)
            {
                string option = args[i];
                bool file = false;

                switch (option[0])
                {
                    case '/':
                        if (Path.DirectorySeparatorChar == option[0])
                            goto default;
                        option = option.Substring(1);
                        break;

                    case '-':
                        int n = 1;
                        if (option.Length > 1 && option[1] == option[0])
                            n++;
                        option = option.Substring(n);
                        break;

                    default:
                        file = true;
                        break;
                }

                if (file)
                {
                    if (script == null)
                        script = option;
                    else
                        Message(ErrorDuplicatePaths, ExitInvalidFunction);
                }
                else
                {
                    switch (option.ToUpperInvariant())
                    {
                        case "GUI":
                            gui = true;
                            break;

                        case "OUT":
                            int n = i + 1;
                            if (n < args.Length)
                            {
                                exe = args[n];
                                i = n;

                                if (exe == "!")
                                {
                                    exe = null;

                                    using (var saveas = new SaveFileDialog())
                                    {
                                        saveas.AddExtension = true;
                                        saveas.AutoUpgradeEnabled = true;
                                        saveas.CheckPathExists = true;
                                        saveas.DefaultExt = "exe";
                                        saveas.Filter = "Application (*.exe)|*.exe";
                                        saveas.OverwritePrompt = true;
                                        saveas.ValidateNames = true;

                                        if (!string.IsNullOrEmpty(script))
                                            saveas.FileName = Path.GetFileNameWithoutExtension(script) + ".exe";

                                        if (saveas.ShowDialog() == DialogResult.OK)
                                            exe = saveas.FileName;
                                    }
                                }
                            }
                            if (exe == null)
                                return Message(ErrorOutputUnspecified, ExitInvalidFunction);
                            break;

                        case "VERSION":
                        case "V":
                            string vers = string.Format("{0} {1}",
                                name, Assembly.GetExecutingAssembly().GetName().Version);
                            return Message(vers, ExitSuccess);

                        case "HELP":
                        case "?":
                            string txt = string.Format("Usage: {0} [{1}gui] [{1}out filename] <source file>",
                                Path.GetFileName(self), Environment.OSVersion.Platform == PlatformID.Unix ? "--" : "/");
                            return Message(txt, ExitSuccess);

                        case "ABOUT":
                            var license = asm.GetManifestResourceStream(typeof(Program).Namespace + ".license.txt");
                            return Message(new StreamReader(license).ReadToEnd(), ExitSuccess);

                        default:
                            return Message(ErrorUnrecognisedSwitch, ExitInvalidFunction);
                    }
                }
            }

            if (script == null)
            {
                if (gui)
                {
                    var docs = new[]
                    {
                        Path.Combine(Path.GetDirectoryName(self), Path.Combine("docs", "index.html")),
                        string.Format("..{0}..{0}Site{0}docs{0}index.html", Path.DirectorySeparatorChar),
                        null
                    };

                    for (int i = 0; i < 2; i++)
                        if (File.Exists(docs[i]))
                            docs[2] = docs[i];

                    bool help = !string.IsNullOrEmpty(docs[2]);

                    string text = (args.Length > 0 || !help ? "Error: " + ErrorNoPaths + "\n\n" : string.Empty) +
                        (help ? "To get started, would you like to view the help documentation?" : string.Empty);

                    var result = MessageBox.Show(text, typeof(Program).Namespace, help ? MessageBoxButtons.YesNo : MessageBoxButtons.OK, MessageBoxIcon.Information);

                    if (help && result == DialogResult.Yes)
                        Process.Start(Path.GetFullPath(docs[2]));

                    return ExitFileNotFound;
                }
                else
                    return Message(ErrorNoPaths, ExitFileNotFound);
            }
            else if (!File.Exists(script))
                return Message(ErrorSourceFileNotFound, ExitFileNotFound);

            #endregion Command line

            #region Compile

            #region Source

            CompilerResults results;
            bool reflect = exe == null;
            var exit = ExitSuccess;

            using (var ahk = new IACodeProvider())
            {
                self = Path.GetDirectoryName(Path.GetFullPath(self));
                var options = new IACompilerParameters
                {
                    MergeFallbackToLink = true
                };

                if (!reflect)
                {
                    if (File.Exists(exe))
                        File.Delete(exe);
                    options.OutputAssembly = exe;
                    options.Merge = !debug;
                }

                options.GenerateExecutable = !reflect;
                options.GenerateInMemory = reflect;

                results = ahk.CompileAssemblyFromFile(options, script);
            }

            #endregion Source

            #region Warnings

            var failed = false;
            string failure;

            using (var warnings = new StringWriter())
            {
                warnings.WriteLine(ErrorErrorsOccurred);
                warnings.WriteLine();

                foreach (CompilerError error in results.Errors)
                {
                    string file = string.IsNullOrEmpty(error.FileName) ? script : error.FileName;

                    if (!error.IsWarning)
                    {
                        failed = true;
                        warnings.WriteLine("{0}:{1} - {2}", Path.GetFileName(file), error.Line, error.ErrorText);
                    }

                    Console.Error.WriteLine("{0} ({1}): ==> {2}", file, error.Line, error.ErrorText);
                }

                failure = warnings.ToString();
            }

            if (failed)
                return Message(gui ? failure : ErrorCompilationFailed, ExitInvalidFunction);

            #endregion Warnings

            #region Execute

            if (reflect || debug)
            {
                GC.Collect();
                GC.WaitForPendingFinalizers();

                try
                {
                    if (results.CompiledAssembly == null)
                        throw new Exception(ErrorCompilationFailed);
                    Environment.SetEnvironmentVariable("SCRIPT", script);
                    results.CompiledAssembly.EntryPoint.Invoke(null, null);
                }

                #region Error

                catch (Exception e)
                {
                    if (e is TargetInvocationException)
                        e = e.InnerException;

                    string msg;

                    using (var error = new StringWriter())
                    {
                        error.WriteLine("{0}: {1}", e.GetType().Name, e.Message);
                        error.WriteLine();
                        error.WriteLine(e.StackTrace);
                        msg = error.ToString();
                    }

            #pragma warning disable 162
                    if (debug)
                    {
                        Console.WriteLine();
                        Console.Write(msg);
                    }
                    else
                        exit = Message("Could not execute: " + e.Message, ExitInvalidFunction);
            #pragma warning restore

                    var trace = Environment.GetEnvironmentVariable(name.ToUpperInvariant() + "_TRACE");

                    try
                    {
                        if (!string.IsNullOrEmpty(trace) && Directory.Exists(Path.GetDirectoryName(trace)))
                        {
                            if (File.Exists(trace))
                                File.Delete(trace);

                            File.WriteAllText(trace, msg);
                        }
                    }
                    catch
                    {
                    }

                    if (debug)
                        Console.Read();
                }

                #endregion Error
            }

            #endregion Execute

            #endregion Compile

            return exit;
        }