/*============================================================================= Project: SharpImage Module: siScriptManager.cs Language: C# Author: Dan Mueller Date: $Date: 2007-07-06 10:57:00 +1000 (Fri, 06 Jul 2007) $ Revision: $Revision: 2 $ Copyright (c) Queensland University of Technology (QUT) 2007. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notices for more information. =============================================================================*/ using System; using System.IO; using System.Diagnostics; using System.Collections; using System.Collections.Generic; using System.Text; using System.Threading; using System.Windows.Forms; using System.Text.RegularExpressions; using IronPython.Hosting; using IronPython.Runtime.Exceptions; using SharpImage.Main; namespace SharpImage.Script { #region siScriptCommandNotSupportedException //========================================================================= public class siScriptCommandNotSupportedException : ArgumentException { public siScriptCommandNotSupportedException(string message, string command) : base(message, command) { } } //========================================================================= #endregion #region siScriptManager Class //========================================================================= public class siScriptManager : IDisposable { #region Instance Variables //===================================================================== private bool m_IsDisposed = false; private bool m_HasScriptBeenFinalised = false; private bool m_HasScriptBeenCompleted = false; private TimeSpan m_SpanScriptStarted; //===================================================================== #endregion #region Construction and Disposal //===================================================================== /// /// Protected constructor. /// /// protected siScriptManager(IApplication parent) { this.m_ParentApplication = parent; this.m_Engine = new PythonEngine(); } /// /// Public constructor. /// /// The parent application. /// The full file path of the script /// to manage. public siScriptManager(IApplication parent, string scriptFilePath) : this(parent) { // Set member properties this.m_ScriptFilePath = scriptFilePath; // Initialise the Engine this.m_Engine = new PythonEngine(); this.GetScriptPathHierarchy(true); this.Engine.Import("Site"); this.Engine.Import("System"); this.Engine.Import("clr"); // Add IApplication to Engine.Globals this.Engine.Globals["ParentApplication"] = parent; this.Engine.Globals["ScriptFilePath"] = this.ScriptFilePath; // Add event handlers dictionary to Engine.Globals Dictionary handlers = new Dictionary(); handlers["ScriptRegisterName"] = new ScriptStringHandler(this.RegisterScriptNameHandler); handlers["ScriptWriteLineToConsole"] = new ScriptStringHandler(this.OnScriptWriteLineToConsole); handlers["ScriptStarted"] = new ScriptEmptyHandler(this.OnScriptStarted); handlers["ScriptCompleted"] = new ScriptCompletedHandler(this.OnScriptCompleted); handlers["ScriptFinalised"] = new ScriptEmptyHandler(this.OnScriptFinalised); handlers["ScriptException"] = new ScriptExceptionHandler(this.OnScriptException); handlers["ScriptFilterStarted"] = new itk.itkTimedEventHandler(this.OnScriptFilterStarted); handlers["ScriptFilterEnded"] = new itk.itkTimedEventHandler(this.OnScriptFilterEnded); handlers["ScriptFilterProgress"] = new itk.itkProgressHandler(this.OnScriptFilterProgress); this.Engine.Globals["Handlers"] = handlers; } /// /// Protected constructor. /// /// /// /// The value to init the ScriptCommand property with. /// The value to init the ScriptParameters property with. protected siScriptManager(IApplication parent, string scriptFilePath, string command, string parameters) : this(parent, scriptFilePath) { this.m_ScriptCommand = command; this.m_ScriptParameters = parameters; } /// /// Deconstructor. /// ~siScriptManager() { this.Dispose(); } /// /// Dispose of resources. /// public void Dispose() { if (this.m_IsDisposed) return; // Dispose of Engine resource if (this.m_Engine != null) { this.m_Engine.Shutdown(); this.m_Engine.Dispose(); this.m_Engine = null; } // Flag that we are disposed this.m_IsDisposed = true; // Tell the GC that the Finalize process no longer needs // to be run for this object. GC.SuppressFinalize(this); } //===================================================================== #endregion #region Properties //===================================================================== #region ParentApplication //===================================================================== private IApplication m_ParentApplication = null; /// /// Gets parent application. /// public IApplication ParentApplication { get { return this.m_ParentApplication; } } //===================================================================== #endregion #region Engine //===================================================================== private PythonEngine m_Engine = null; /// /// Gets the PythonEngine associated with this script. /// private PythonEngine Engine { get { return this.m_Engine; } } //===================================================================== #endregion #region Code //===================================================================== private CompiledCode m_Code = null; private bool m_IsCodeCompiled = false; /// /// Gets the CompiledCode associated with this script. /// This is only valid after calling CompileScript(). /// protected CompiledCode Code { get { return this.m_Code; } } /// /// Gets if the code has been successfully compiled. /// protected bool IsCodeCompiled { get { return this.m_IsCodeCompiled; } } //===================================================================== #endregion #region ScriptFilePath //===================================================================== private string m_ScriptFilePath = string.Empty; /// /// Gets the full path of the script file associated with this /// ScriptManager instance. /// public string ScriptFilePath { get { return this.m_ScriptFilePath; } } //===================================================================== #endregion #region ScriptName //===================================================================== private string m_ScriptName = string.Empty; /// /// Gets the name the script uses to identify itself. This property is /// only valid after a successful call to InitializeScript(). /// public string ScriptName { get { return this.m_ScriptName; } } //===================================================================== #endregion #region ScriptCommand //===================================================================== private string m_ScriptCommand = "run"; /// /// Gets a specific command to execute. /// To run the script the command should be "run", to display help /// information the command should be "help". "run" is the default /// command for newly created ScriptManagers. /// public string ScriptCommand { get { return this.m_ScriptCommand; } } //===================================================================== #endregion #region ScriptParameters //===================================================================== private string m_ScriptParameters = string.Empty; /// /// Gets the parameters to initialise the script object. /// Each name-value pair is separated by a space. /// For example: "ThresholdLower=50 ThresholdUpper=100" /// public string ScriptParameters { get { return this.m_ScriptParameters; } } //===================================================================== #endregion //===================================================================== #endregion #region Events and Delegates //===================================================================== public delegate void ScriptHandler(siScriptManager manager); private delegate void ScriptEmptyHandler(); private delegate void ScriptCompletedHandler(bool success); private delegate void ScriptStringHandler(string info); private delegate void ScriptExceptionHandler(Exception ex); #region ScriptFinalised //============================================================================ private ScriptHandler m_EventStorage_ScriptFinalised; /// /// An event raised when the itk.itkProcessObject has /// started processing. /// public event ScriptHandler ScriptFinalised { add { this.m_EventStorage_ScriptFinalised += value; } remove { this.m_EventStorage_ScriptFinalised -= value; } } /// /// Raise the ScriptCompleted event. /// /// public void RaiseScriptFinalised() { // Check we have not already raised this event if (!this.m_HasScriptBeenFinalised) { // Flag we have raised the finalised event this.m_HasScriptBeenFinalised = true; // Raise event if (this.m_EventStorage_ScriptFinalised != null) this.m_EventStorage_ScriptFinalised(this); } } //============================================================================ #endregion //===================================================================== #endregion #region Public Static Methods //===================================================================== /// /// Creates a ScriptManager from the given command string. /// Returns null if an error occurred while executing the command. /// The error is displayed in the script console. /// /// /// /// The absolute path of the current directory. /// The newly created script manager waiting to be /// executed OR null on error. public static siScriptManager CreateFromCommand(IApplication parent, string command, string currentDirectory) { siScriptManager result = null; try { // Check command is not empty if (command == null || command.Length == 0) throw new siScriptCommandNotSupportedException("You entered an empty command. Please enter either 'run