bin/projects/dbatools/dbatools/Runspace/RunspaceContainer.cs
using System; using System.Management.Automation; using System.Management.Automation.Runspaces; using System.Threading; namespace Sqlcollaborative.Dbatools.Runspace { /// <summary> /// Class that contains the logic necessary to manage a unique runspace /// </summary> public class RunspaceContainer { private ScriptBlock Script; private PowerShell Runspace; /// <summary> /// The name of the runspace. /// </summary> public readonly string Name; /// <summary> /// The Guid of the running Runspace /// </summary> public Guid RunspaceGuid { get { return Runspace.Runspace.InstanceId; } } /// <summary> /// Sets the script to execute in the runspace. Will NOT take immediate effect. Only after restarting the runspace will it be used. /// </summary> /// <param name="Script">The scriptblock to execute</param> public void SetScript(ScriptBlock Script) { this.Script = Script; } /// <summary> /// The state the runspace currently is in. /// </summary> public DbaRunspaceState State { get { return _State; } } private DbaRunspaceState _State = DbaRunspaceState.Stopped; /// <summary> /// Starts the Runspace. /// </summary> public void Start() { if ((Runspace != null) && (State == DbaRunspaceState.Stopped)) { Kill(); } if (Runspace == null) { Runspace = PowerShell.Create(); try { SetName(Runspace.Runspace); } catch { } Runspace.AddScript(Script.ToString()); _State = DbaRunspaceState.Running; try { Runspace.BeginInvoke(); } catch { _State = DbaRunspaceState.Stopped; } } } /// <summary> /// Sets the name on a runspace. This WILL FAIL for PowerShell v3! /// </summary> /// <param name="Runspace">The runspace to be named</param> private void SetName(System.Management.Automation.Runspaces.Runspace Runspace) { #if (NORUNSPACENAME) #else Runspace.Name = Name; #endif } /// <summary> /// Gracefully stops the Runspace /// </summary> public void Stop() { _State = DbaRunspaceState.Stopping; int i = 0; // Wait up to the limit for the running script to notice and kill itself if ((Runspace != null) && (Runspace.Runspace != null)) { while ((Runspace.Runspace.RunspaceAvailability != RunspaceAvailability.Available) && (i < (10 * RunspaceHost.StopTimeoutSeconds))) { i++; Thread.Sleep(100); } } Kill(); } /// <summary> /// Very ungracefully kills the runspace. Use only in the most dire emergency. /// </summary> public void Kill() { if (Runspace != null) { try { Runspace.Runspace.Close(); } catch { } Runspace.Dispose(); Runspace = null; } _State = DbaRunspaceState.Stopped; } /// <summary> /// Signals the registered runspace has stopped execution /// </summary> public void SignalStopped() { _State = DbaRunspaceState.Stopped; } /// <summary> /// Creates a new runspace container with the basic information needed /// </summary> /// <param name="Name">The name of the Runspace</param> /// <param name="Script">The code using the runspace logic</param> public RunspaceContainer(string Name, ScriptBlock Script) { this.Name = Name.ToLower(); this.Script = Script; } } } |