Dude, you totally rock! I'll be giving this a try this weekend. -Abe
On 11/11/05, Elliott Draper <[EMAIL PROTECTED]> wrote: > Hi Abe, > > Abe Gillespie wrote: > > >*snip > >mono script_host.exe MyScript.cs myarg1 myarg2 > > > >*snip > >Has anyone out there done something or started a project like this? > > > > > Give the attached source code a try :-) I'm not claiming it's perfect, > but it's something I knocked up while I was bored this afternoon, and > you may be able to use it or tweak it to what you need. It uses the > features of CodeDom, available both in .Net and Mono, to compile the > source file to an in-memory assembly, where the code can then be > executed. The file "MonoScript.cs" can be compiled on its own to provide > the actual script execution tool, and also attached is a sample "script" > file ("Test.cs") that you can use to give it a bash. Simply compile the > MonoScript tool: > > mcs MonoScript.cs > > And then it's as easy as running: > > mono MonoScript.exe --sourceFile:Test.cs > > If for example your source file has a reference to System.Data then you > can simply run: > > mono MonoScript.exe --sourceFile:Test.cs --references:System.Data.dll > > For the full usage of the program, run: > > mono MonoScript.exe --displayUsage:true > > Any arguments you specify that MonoScript doesn't recognize will be > forwarded onto the "script" application, you can see this by appending > as many arguments as you want to the test script: > > mono MonoScript.exe --sourceFile:Test.cs test1 test2 test3 > > Have a play, and give me a shout if you run into any bugs or problems > with it and I'll do my best to fix them, failing that, jump right in and > tweak the code yourself ;-) > > If anyone else finds the code useful, let me know and I'll get the > entire thing (project files, a build file maybe, a bigger testsuite > perhaps?) up on my website as a package. Likewise if anyone has any > comments, let me have 'em! > > >-Abe > > > > > Cheers, > -= El =- > > >On 11/10/05, Kornél Pál <[EMAIL PROTECTED]> wrote: > > > > > >>Hi, > >> > >>You have to compile C# code using mcs that will result in a .exe assembly > >>that can be executed using mono: > >> > >>$mcs some.cs > >>$mono some.exe > >> > >>If you prefer you can write a shell script that will do this as a single > >>step. > >> > >>Kornél > >> > >>----- Original Message ----- > >>From: "Abe Gillespie" <[EMAIL PROTECTED]> > >>To: "MonoList" <mono-list@lists.ximian.com> > >>Sent: Friday, November 11, 2005 1:02 AM > >>Subject: [Mono-list] Scripting the Linux OS with Mono > >> > >> > >>Hey all, > >> > >>I was wondering if there's any easy way to run C# scripts in Mono. > >>I'm fairly new to Linux (just at about a year) and I'd like to avoid > >>learning yet another language (Perl, sh, etc.). Has anyone written a > >>.Net program that takes a file as input and runs that code? Perhaps > >>Mono can do this natively? How cool would it be to have startup > >>scripts written in C#?! > >> > >>Thanks for the help as always. > >>-Abe > >>_______________________________________________ > >>Mono-list maillist - Mono-list@lists.ximian.com > >>http://lists.ximian.com/mailman/listinfo/mono-list > >> > >> > >> > >> > >_______________________________________________ > >Mono-list maillist - Mono-list@lists.ximian.com > >http://lists.ximian.com/mailman/listinfo/mono-list > > > > > > > > using System; > > public class MonoScriptTest > { > //This simply displays the amount of arguments passed into it > public static void Main(string[] args) > { > Console.WriteLine(string.Format("MonoScript: test script, {0} > arguments",args.Length.ToString())); > } > } > > using System; > using System.CodeDom; > using System.CodeDom.Compiler; > using System.Collections.Specialized; > using System.Reflection; > > namespace MonoScript > { > /// <summary> > /// This allows the execution of a .cs file as if it were a program, > compiling it on the fly then executing it > /// > /// Example syntax: > /// > /// MonoScript /s:myscript.cs /r:System.Drawing.dll This > would execute the code within the > /// file myscript.cs, and reference System.Drawing.dll when compiling it > /// > /// MonoScript /s:myscript.cs /r:System.Data.dll /n:true /v:true This > would compile the code within the > /// file myscript.cs, reference System.Data.dll when doing it, stop the > MonoScript logo from displaying > /// when run, and also ensure that ONLY compilation takes place, not > execution, for validation purposes > /// </summary> > class MonoScript > { > /// <summary> > /// These are our options for the script to execute > /// </summary> > static MonoScriptOptions Options; > > /// <summary> > /// Main entry point > /// </summary> > /// <param name="args"></param> > static void Main(string[] args) > { > //Create our options from the command line args > Options = new MonoScriptOptions(args); > > //Only show the logo if we haven't been told not to > if(!Options.NoLogo) > Logo(); > > //If the user has requested the program usage, then show it here > if (Options.DisplayUsage) > { > Usage(); > return; > } > > //This will hold our in-memory compiled assembly > Assembly assembly = null; > > try > { > //Compile our script to an assembly > assembly = CompileFile(); > > //Ensure we have an assembly > if (assembly == null) > throw new Exception("No assembly generated!"); > } > catch (Exception ex) > { > //Display any errors found while compiling > Console.WriteLine(string.Format( > "Exception caught while compiling script:{0}{1}{0}", > Environment.NewLine, > ex.ToString())); > > return; > } > > //If we are only validating (compiling) the script, then exit here > if (Options.ValidateOnly) > { > Console.WriteLine("Validation complete"); > return; > } > > try > { > //Execute the script > ExecuteAssembly(assembly); > } > catch (Exception ex) > { > //Catch any errors while executing it > Console.WriteLine(string.Format( > "Exception caught while executing script:{0}{1}{0}", > Environment.NewLine, > ex.ToString())); > > return; > } > } > > /// <summary> > /// This outputs the program logo > /// </summary> > static void Logo() > { > Console.WriteLine("MonoScript: (c) 2005, Elliott Draper <[EMAIL > PROTECTED]>"); > } > > /// <summary> > /// This outputs the usage of the app > /// </summary> > static void Usage() > { > Console.WriteLine("Usage: MonoScript --sourceFile:[VALUE] [ARGS] > where [ARGS] can optionally be one of the following:"); > Console.WriteLine("--references:[VALUE], -r:[VALUE], /r:[VALUE] > : any references needed to compile the script"); > Console.WriteLine("--noLogo:[VALUE], -n:[VALUE], /n:[VALUE] > : stops from showing the MonoScript logo"); > Console.WriteLine("--displayUsage:[VALUE], -d:[VALUE], /d:[VALUE] > : displays this usage info"); > Console.WriteLine("--validateOnly:[VALUE], -v:[VALUE], /v:[VALUE] > : validates the script by compiling it, but doesn't execute it"); > } > > /// <summary> > /// This compiles the specified file into an assembly, exceptioning > on error > /// </summary> > /// <returns></returns> > static Assembly CompileFile() > { > //Setup the parameters > CompilerParameters parameters = new CompilerParameters(); > foreach (string reference in Options.References) > parameters.ReferencedAssemblies.Add(reference); > parameters.GenerateInMemory = true; > > //Create the provider and compiler > CodeDomProvider provider = new > Microsoft.CSharp.CSharpCodeProvider(); > if (provider == null) > throw new Exception("Cannot create C# code provider!"); > ICodeCompiler compiler = provider.CreateCompiler(); > if (compiler == null) > throw new Exception("Cannot create C# compiler!"); > //Compile the file with the specified parameters > CompilerResults results = compiler.CompileAssemblyFromFile( > parameters, > Options.SourceFile); > //Grab and validate the results > if (results == null) > throw new Exception("Could not retrieve results from > compilation!"); > if (results.Errors.HasErrors) > throw new Exception(results.Errors[0].ErrorText); > //Return the compiled assembly > return results.CompiledAssembly; > } > > /// <summary> > /// This executes the specified compiled assembly > /// </summary> > /// <param name="assembly"></param> > static void ExecuteAssembly(Assembly assembly) > { > //Invoke the entry point found for the assembly, with the > specified arguments > GetEntryPoint(assembly).GetMethod("Main").Invoke(null, new > object[1] { Options.ScriptArgs }); > } > > /// <summary> > /// This attempts to locate a type with a static "Main" method within > the generated script assembly > /// </summary> > /// <param name="assembly"></param> > /// <returns></returns> > static Type GetEntryPoint(Assembly assembly) > { > //Loop through all of the generated types > foreach (Type type in assembly.GetTypes()) > { > //If we find one that has a static Main method, lets return it > if (type.GetMethod("Main") != null && > type.GetMethod("Main").IsStatic) > return type; > } > //If we get to here, we got no entry point :-( > throw new Exception("Unable to find a class with a valid entry > point within the script!"); > } > } > > /// <summary> > /// This contains options for calling MonoScript with > /// </summary> > class MonoScriptOptions > { > #region Private Variables > > private string[] _references = new string[0]; > private string _sourceFile; > private bool _noLogo = false; > private bool _displayUsage = false; > private bool _validateOnly = false; > private StringCollection optionArgs = new StringCollection(); > > #endregion > > #region Properties > > /// <summary> > /// This specifies that no logo should be shown for the MonoScript app > /// </summary> > public bool NoLogo > { > get > { > return _noLogo; > } > } > > /// <summary> > /// This specifies that the MonoScript usage should be displayed > /// </summary> > public bool DisplayUsage > { > get > { > return _displayUsage; > } > } > > /// <summary> > /// This specifies that the source file shouldn't be executed as a > script; just that it should be > /// compiled and validated to ensure it is a valid source file > /// </summary> > public bool ValidateOnly > { > get > { > return _validateOnly; > } > } > > /// <summary> > /// Any assembly references needed to compile the script > /// </summary> > public string[] References > { > get > { > return _references; > } > } > > /// <summary> > /// The source file acting as the script > /// </summary> > public string SourceFile > { > get > { > if(_sourceFile==null) > throw new Exception("No source file specified!"); > return _sourceFile; > } > } > > /// <summary> > /// The arguments to call the script with > /// </summary> > public string[] ScriptArgs > { > get > { > string[] args = new string[optionArgs.Count]; > for (int i = 0; i < args.Length; i++) > args[i] = optionArgs[i]; > return args; > } > } > > #endregion > > #region Constructor > > /// <summary> > /// Default constructor > /// </summary> > public MonoScriptOptions(string[] args) > { > //Validate > if(args==null||args.Length==0) > throw new Exception("No arguments specified!"); > > //Add in args > optionArgs.AddRange(args); > > //Fill out options > _sourceFile = GetArgument("sourceFile"); > > string noLogo = GetArgument("noLogo"); > _noLogo = (noLogo != null && noLogo.ToLower() == "true") ? true : > false; > > string displayUsage = GetArgument("displayUsage"); > _displayUsage = (displayUsage != null && displayUsage.ToLower() > == "true") ? true : false; > > string validateOnly = GetArgument("validateOnly"); > _validateOnly = (validateOnly != null && validateOnly.ToLower() > == "true") ? true : false; > > string references = GetArgument("references"); > if(references!=null) > _references = references.Split(Convert.ToChar(",")); > } > > #endregion > > #region Methods > > /// <summary> > /// This retrieves an argument value from the list of arguments > /// If it finds a requested argument, it then removes it from the > list of arguments > /// > /// If you request the argument for the command "references", any > argument such as: > /// --references:[VALUE] > /// -r:[VALUE] > /// /r:[VALUE] > /// > /// will all result in the returning of "[VALUE]" > /// If more than one is specified, they will be taken in the above > order > /// </summary> > /// <param name="requestedCmd"></param> > /// <returns></returns> > private string GetArgument(string requestedCmd) > { > //These variables are used throughout > string value = null; > string arg = null; > //Loop through all arguments > for(int i=0;i<optionArgs.Count;i++) > { > arg = optionArgs[i]; > //Prepare the first format of the requested command to search > for > string cmd = string.Format("--{0}:", requestedCmd); > if (arg.IndexOf(cmd) != -1) > { > //If it's found, then set the value, and break the loop > value = arg.Substring( > 0 + cmd.Length, > arg.Length - cmd.Length); > break; > } > //Try the next format of the requested command > cmd = string.Format("-{0}:", requestedCmd[0]); > if (arg.IndexOf(cmd) != -1) > { > //Again, if found, set the value and break out of the loop > value = arg.Substring( > 0 + cmd.Length, > arg.Length - cmd.Length); > break; > } > //Finally try the last format of the requested command > cmd = string.Format("/{0}:", requestedCmd[0]); > if (arg.IndexOf(cmd) != -1) > { > //Set value, break loop > value = arg.Substring( > 0 + cmd.Length, > arg.Length - cmd.Length); > break; > } > } > > //If we have got here with a value set, then we found our > argument value, so remove the argument, > //and return our value > if (value != null) > { > optionArgs.Remove(arg); > return value; > } > > //Otherwise, return null > return null; > } > > #endregion > } > } > > > _______________________________________________ Mono-list maillist - Mono-list@lists.ximian.com http://lists.ximian.com/mailman/listinfo/mono-list