CSharp/PowerShellDataSource.cs
namespace ShowUI
{ using System; using System.Collections.Generic; using System.Text; using System.ComponentModel; using System.Collections.ObjectModel; using System.Management.Automation; using System.Windows; using System.Collections; using System.Management.Automation.Runspaces; using System.Timers; using System.Windows.Threading; using System.Threading; public class PowerShellDataSource : INotifyPropertyChanged { Hashtable resources = new Hashtable(); public Hashtable Resources { get { return this.resources; } } public Dispatcher Dispatcher { get; set; } object RunOnUIThread(DispatcherOperationCallback dispatcherMethod, bool async) { if (Application.Current != null) { if (Application.Current.Dispatcher.Thread == Thread.CurrentThread) { // This avoids dispatching to the UI thread if we are already in the UI thread. // Without this runing a command like 1/0 was throwing due to nested dispatches. return dispatcherMethod.Invoke(null); } } Exception e = null; object returnValue = null; SynchronizationContext sync = new DispatcherSynchronizationContext(Dispatcher); if (sync == null) { return null; } if (async) { sync.Post( new SendOrPostCallback(delegate(object obj) { try { returnValue = dispatcherMethod.Invoke(obj); } catch (Exception uiException) { e = uiException; } }), null); } else { sync.Send( new SendOrPostCallback(delegate(object obj) { try { returnValue = dispatcherMethod.Invoke(obj); } catch (Exception uiException) { e = uiException; } }), null); } if (e != null) { throw new System.Reflection.TargetInvocationException(e.Message, e); } return returnValue; } public Object Parent { get { return this.parent; } set { this.parent = value; if (this.parent != null && this.parent.GetType().GetProperty("Dispatcher") != null) { Dispatcher = this.parent.GetType().GetProperty("Dispatcher").GetValue(this.parent, null) as Dispatcher; } } } private Object parent; public PSObject[] Output { get { PSObject[] returnValue = new PSObject[outputCollection.Count]; outputCollection.CopyTo(returnValue, 0); return returnValue; } } PSObject lastOutput; public PSObject LastOutput { get { return lastOutput; } } public ErrorRecord[] Error { get { ErrorRecord[] returnValue = new ErrorRecord[powerShellCommand.Streams.Error.Count]; powerShellCommand.Streams.Error.CopyTo(returnValue, 0); return returnValue; } } ErrorRecord lastError; public ErrorRecord LastError { get { return this.lastError; } } public WarningRecord[] Warning { get { WarningRecord[] returnValue = new WarningRecord[powerShellCommand.Streams.Warning.Count]; powerShellCommand.Streams.Warning.CopyTo(returnValue, 0); return returnValue; } } WarningRecord lastWarning; public WarningRecord LastWarning { get { return lastWarning; } } public VerboseRecord[] Verbose { get { VerboseRecord[] returnValue = new VerboseRecord[powerShellCommand.Streams.Verbose.Count]; powerShellCommand.Streams.Verbose.CopyTo(returnValue, 0); return returnValue; } } VerboseRecord lastVerbose; public VerboseRecord LastVerbose { get { return lastVerbose; } } public DebugRecord[] Debug { get { DebugRecord[] returnValue = new DebugRecord[powerShellCommand.Streams.Debug.Count]; powerShellCommand.Streams.Debug.CopyTo(returnValue, 0); return returnValue; } } DebugRecord lastDebug; public DebugRecord LastDebug { get { return lastDebug; } } public ProgressRecord[] Progress { get { ProgressRecord[] returnValue = new ProgressRecord[powerShellCommand.Streams.Progress.Count]; powerShellCommand.Streams.Progress.CopyTo(returnValue, 0); return returnValue; } } public PSObject[] TimeStampedOutput { get { PSObject[] returnValue = new PSObject[timeStampedOutput.Count]; timeStampedOutput.CopyTo(returnValue, 0); return returnValue; } } private PSObject lastTimeStampedOutput; public PSObject LastTimeStampedOutput { get { return this.lastTimeStampedOutput; } } ProgressRecord lastProgress; public ProgressRecord LastProgress { get { return lastProgress; } } public PowerShell Command { get { return powerShellCommand; } } public bool IsFinished { get { return (powerShellCommand.InvocationStateInfo.State == PSInvocationState.Completed || powerShellCommand.InvocationStateInfo.State == PSInvocationState.Failed || powerShellCommand.InvocationStateInfo.State == PSInvocationState.Stopped); } } public bool IsRunning { get { return (powerShellCommand.InvocationStateInfo.State == PSInvocationState.Running || powerShellCommand.InvocationStateInfo.State == PSInvocationState.Stopping); } } string script; PSDataCollection<PSObject> timeStampedOutput; public string Script { get { return script; } set { script = value; try { powerShellCommand.Commands.Clear(); powerShellCommand.AddScript(script, false); lastDebug = null; lastError = null; lastTimeStampedOutput = null; outputCollection.Clear(); timeStampedOutput.Clear(); lastOutput = null; lastProgress = null; lastVerbose = null; lastWarning = null; powerShellCommand.BeginInvoke<Object, PSObject>(null, outputCollection); } catch { } } } void powerShellCommand_InvocationStateChanged(object sender, PSInvocationStateChangedEventArgs e) { if (e.InvocationStateInfo.State == PSInvocationState.Failed) { ErrorRecord err = new ErrorRecord(e.InvocationStateInfo.Reason, "PowerShellDataSource.TerminatingError", ErrorCategory.InvalidOperation, powerShellCommand); powerShellCommand.Streams.Error.Add(err); } if (Dispatcher != null) { RunOnUIThread( new DispatcherOperationCallback( delegate { NotifyInvocationStateChanged(); return null; }), true); } else { NotifyInvocationStateChanged(); } } PowerShell powerShellCommand; PSDataCollection<PSObject> outputCollection; public PowerShellDataSource() { powerShellCommand = PowerShell.Create(); Runspace runspace = RunspaceFactory.CreateRunspace(); runspace.Open(); powerShellCommand.Runspace = runspace; outputCollection = new PSDataCollection<PSObject>(); timeStampedOutput = new PSDataCollection<PSObject>(); outputCollection.DataAdded += new EventHandler<DataAddedEventArgs>(outputCollection_DataAdded); timeStampedOutput.DataAdded += new EventHandler<DataAddedEventArgs>(timeStampedOutput_DataAdded); powerShellCommand.Streams.Debug.DataAdded += new EventHandler<DataAddedEventArgs>(Debug_DataAdded); powerShellCommand.Streams.Error.DataAdded += new EventHandler<DataAddedEventArgs>(Error_DataAdded); powerShellCommand.Streams.Verbose.DataAdded += new EventHandler<DataAddedEventArgs>(Verbose_DataAdded); powerShellCommand.Streams.Progress.DataAdded += new EventHandler<DataAddedEventArgs>(Progress_DataAdded); powerShellCommand.Streams.Warning.DataAdded += new EventHandler<DataAddedEventArgs>(Warning_DataAdded); } #region Notification Methods void NotifyTimeStampedOutputChanged() { object sender; if (this.Parent != null) { sender = this.Parent; } else { sender = this; } if (PropertyChanged != null) { PropertyChanged(sender, new PropertyChangedEventArgs("TimeStampedOutput")); } if (TimeStampedOutputChanged != null) { TimeStampedOutputChanged(sender, new PropertyChangedEventArgs("TimeStampedOutput")); } } void NotifyInvocationStateChanged() { object sender; if (this.Parent != null) { sender = this.Parent; } else { sender = this; } if (PropertyChanged != null) { PropertyChanged(sender, new PropertyChangedEventArgs("IsFinished")); PropertyChanged(sender, new PropertyChangedEventArgs("IsRunning")); } if (IsFinishedChanged != null) { IsFinishedChanged(sender, new PropertyChangedEventArgs("IsFinished")); } if (IsRunningChanged != null) { IsRunningChanged(sender, new PropertyChangedEventArgs("IsRunning")); } } void NotifyErrorChanged() { object sender; if (this.Parent != null) { sender = this.Parent; } else { sender = this; } if (PropertyChanged != null) { PropertyChanged(sender, new PropertyChangedEventArgs("Error")); PropertyChanged(sender, new PropertyChangedEventArgs("LastError")); } if (ErrorChanged != null) { ErrorChanged(sender, new PropertyChangedEventArgs("Error")); } } void NotifyDebugChanged() { object sender; if (this.Parent != null) { sender = this.Parent; } else { sender = this; } if (PropertyChanged != null) { PropertyChanged(sender, new PropertyChangedEventArgs("Debug")); PropertyChanged(sender, new PropertyChangedEventArgs("LastDebug")); } if (DebugChanged != null) { DebugChanged(sender, new PropertyChangedEventArgs("Debug")); } } void NotifyOutputChanged() { object sender; if (this.Parent != null) { sender = this.Parent; } else { sender = this; } if (PropertyChanged != null) { PropertyChanged(sender, new PropertyChangedEventArgs("Output")); PropertyChanged(sender, new PropertyChangedEventArgs("LastOutput")); } if (OutputChanged != null) { OutputChanged(sender, new PropertyChangedEventArgs("Output")); } } void NotifyWarningChanged() { object sender; if (this.Parent != null) { sender = this.Parent; } else { sender = this; } if (PropertyChanged != null) { PropertyChanged(sender, new PropertyChangedEventArgs("Warning")); PropertyChanged(sender, new PropertyChangedEventArgs("LastWarning")); } if (WarningChanged != null) { WarningChanged(sender, new PropertyChangedEventArgs("Warning")); } } void NotifyVerboseChanged() { object sender; if (this.Parent != null) { sender = this.Parent; } else { sender = this; } if (PropertyChanged != null) { PropertyChanged(sender, new PropertyChangedEventArgs("Verbose")); PropertyChanged(sender, new PropertyChangedEventArgs("LastVerbose")); } if (VerboseChanged != null) { VerboseChanged(sender, new PropertyChangedEventArgs("Verbose")); } } void NotifyProgressChanged() { object sender; if (this.Parent != null) { sender = this.Parent; } else { sender = this; } if (PropertyChanged != null) { PropertyChanged(sender, new PropertyChangedEventArgs("Progress")); PropertyChanged(sender, new PropertyChangedEventArgs("LastProgress")); } if (ProgressChanged != null) { ProgressChanged(sender, new PropertyChangedEventArgs("Progress")); } } #endregion void timeStampedOutput_DataAdded(object sender, DataAddedEventArgs e) { PSDataCollection<PSObject> collection = sender as PSDataCollection<PSObject>; lastTimeStampedOutput = collection[e.Index]; if (Dispatcher != null) { RunOnUIThread( new DispatcherOperationCallback( delegate { NotifyTimeStampedOutputChanged(); return null; }), true); } else { NotifyTimeStampedOutputChanged(); } } void Debug_DataAdded(object sender, DataAddedEventArgs e) { PSDataCollection<DebugRecord> collection = sender as PSDataCollection<DebugRecord>; lastDebug = collection[e.Index]; PSObject psObj = new PSObject(lastDebug); PSPropertyInfo propInfo = new PSNoteProperty("TimeStamp", DateTime.Now); psObj.Properties.Add(new PSNoteProperty("Stream", "Debug")); psObj.Properties.Add(propInfo); timeStampedOutput.Add(psObj); if (Dispatcher != null) { RunOnUIThread( new DispatcherOperationCallback( delegate { NotifyDebugChanged(); return null; }), true); } else { NotifyDebugChanged(); } } void Error_DataAdded(object sender, DataAddedEventArgs e) { PSDataCollection<ErrorRecord> collection = sender as PSDataCollection<ErrorRecord>; this.lastError = collection[e.Index]; PSObject psObj = new PSObject(lastError); PSPropertyInfo propInfo = new PSNoteProperty("TimeStamp", DateTime.Now); psObj.Properties.Add(new PSNoteProperty("Stream", "Error")); psObj.Properties.Add(propInfo); timeStampedOutput.Add(psObj); if (Dispatcher != null) { RunOnUIThread( new DispatcherOperationCallback( delegate { NotifyErrorChanged(); return null; }), true); } else { NotifyErrorChanged(); } } void Warning_DataAdded(object sender, DataAddedEventArgs e) { PSDataCollection<WarningRecord> collection = sender as PSDataCollection<WarningRecord>; lastWarning = collection[e.Index]; PSObject psObj = new PSObject(lastWarning); psObj.Properties.Add(new PSNoteProperty("TimeStamp", DateTime.Now)); psObj.Properties.Add(new PSNoteProperty("Stream", "Warning")); timeStampedOutput.Add(psObj); if (Dispatcher != null) { RunOnUIThread( new DispatcherOperationCallback( delegate { NotifyWarningChanged(); return null; }), true); } else { NotifyWarningChanged(); } } void Verbose_DataAdded(object sender, DataAddedEventArgs e) { PSDataCollection<VerboseRecord> collection = sender as PSDataCollection<VerboseRecord>; lastVerbose = collection[e.Index]; PSObject psObj = new PSObject(lastVerbose); PSPropertyInfo propInfo = new PSNoteProperty("TimeStamp", DateTime.Now); psObj.Properties.Add(new PSNoteProperty("Stream", "Verbose")); psObj.Properties.Add(propInfo); timeStampedOutput.Add(psObj); if (Dispatcher != null) { RunOnUIThread( new DispatcherOperationCallback( delegate { NotifyVerboseChanged(); return null; }), true); } else { NotifyVerboseChanged(); } } void Progress_DataAdded(object sender, DataAddedEventArgs e) { PSDataCollection<ProgressRecord> collection = sender as PSDataCollection<ProgressRecord>; lastProgress = collection[e.Index]; PSObject psObj = new PSObject(lastProgress); PSPropertyInfo propInfo = new PSNoteProperty("TimeStamp", DateTime.Now); psObj.Properties.Add(new PSNoteProperty("Stream", "Progress")); psObj.Properties.Add(propInfo); timeStampedOutput.Add(psObj); if (Dispatcher != null) { RunOnUIThread( new DispatcherOperationCallback( delegate { NotifyProgressChanged(); return null; }), true); } else { NotifyProgressChanged(); } } void outputCollection_DataAdded(object sender, DataAddedEventArgs e) { PSDataCollection<PSObject> collection = sender as PSDataCollection<PSObject>; lastOutput = collection[e.Index]; PSObject psObj = new PSObject(lastOutput); PSPropertyInfo propInfo = new PSNoteProperty("TimeStamp", DateTime.Now); psObj.Properties.Add(new PSNoteProperty("Stream", "Output")); psObj.Properties.Add(propInfo); timeStampedOutput.Add(psObj); if (Dispatcher != null) { RunOnUIThread( new DispatcherOperationCallback( delegate { NotifyOutputChanged(); return null; }), true); } else { NotifyOutputChanged(); } } public event PropertyChangedEventHandler PropertyChanged; public event PropertyChangedEventHandler OutputChanged; public event PropertyChangedEventHandler ErrorChanged; public event PropertyChangedEventHandler WarningChanged; public event PropertyChangedEventHandler DebugChanged; public event PropertyChangedEventHandler VerboseChanged; public event PropertyChangedEventHandler ProgressChanged; public event PropertyChangedEventHandler IsFinishedChanged; public event PropertyChangedEventHandler IsRunningChanged; public event PropertyChangedEventHandler TimeStampedOutputChanged; } } |