using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;
using System.ComponentModel;
using System.Configuration;
using System.Collections.ObjectModel;
using System.Management.Automation;
using System.Management.Automation.Runspaces;
namespace Powershell.Blogs {
/// <summary>
/// Class implemeting Invoke-Apartment
/// </summary>
[Cmdlet("Invoke", "Apartment")]
public sealed
class
InvokeApartmentCommand : PSCmdlet {
internal class ExecutionResult {
private object output;
private Exception error;
public Object Output {
get { return output; }
set { output = value; }
}
public Exception Error {
get { return error; }
set { error = value; }
}
}
#region Private Data
private ManualResetEvent waitHandle;
private Runspace runspace;
private Runspace Runspace {
get {
return runspace;
}
set {
runspace = value;
}
}
#endregion
#region parameters
private ScriptBlock command;
private ApartmentState apartment = ApartmentState.MTA;
/// <summary>
/// Apartment to run the cmdlet int
/// </summary>
[Parameter(Position = 0, Mandatory = true)]
public ApartmentState Apartment {
get { return apartment; }
set { apartment = value; }
}
/// <summary>
/// Command to execute.
/// </summary>
[Parameter(Position = 1, Mandatory = true, ValueFromPipeline = true)]
public ScriptBlock Expression {
get { return command; }
set { command = value; }
}
#endregion parameters
protected override void BeginProcessing() {
// Set the runspace
Runspace = Runspace.DefaultRunspace;
}
/// <summary>
/// For each record, execute it, and push the results into the
/// success stream.
/// </summary>
protected override void ProcessRecord() {
ExecutionResult result = new ExecutionResult();
if (Thread.CurrentThread.GetApartmentState() == apartment) {
// Since the current apartment state is same as the one requested
// do the work in same thread.
DoWork(result);
} else {
// the apartment state is different..perform the task in
// a differnt thread.
Thread executionThread = new Thread(new ParameterizedThreadStart(PerformExecution));
executionThread.SetApartmentState(apartment);
// Create a handle to wait for completion
waitHandle = new ManualResetEvent(false);
executionThread.Start(result);
waitHandle.WaitOne();
}
if (null != result.Error) {
throw result.Error;
}
if (null != result.Output) {
WriteObject(result.Output);
}
}
private void PerformExecution(object outputToWriteTo) {
ExecutionResult result = (ExecutionResult)outputToWriteTo;
// Use the runspace to execute the script
Runspace.DefaultRunspace = Runspace;
DoWork(result);
if (null != waitHandle) {
waitHandle.Set();
}
}
private void DoWork(ExecutionResult result) {
try {
//ScriptBlock myScriptBlock = InvokeCommand.NewScriptBlock(Expression);
ScriptBlock myScriptBlock = Expression;
result.Output = myScriptBlock.InvokeReturnAsIs(null);
} catch (Exception e) {
result.Error = e;
}
}
}
/// <summary>
/// Create this sample as a PowerShell snap-in
/// </summary>
[RunInstaller(true)]
public class InvokeApartmentPSSnapIn : PSSnapIn {
/// <summary>
/// Create an instance of the InvokeApartmentPSSnapIn
/// </summary>
public InvokeApartmentPSSnapIn()
: base() {
}
/// <summary>
/// Get a name for this PowerShell snap-in. This name will be used in registering
/// this PowerShell snap-in.
/// </summary>
public override string Name {
get {
return "InvokeApartment";
}
}
/// <summary>
/// Vendor information for this PowerShell snap-in.
/// </summary>
public override string Vendor {
get {
return "PowershellBlog";
}
}
/// <summary>
/// Description of this PowerShell snap-in.
/// </summary>
public override string Description {
get {
return "This is a PowerShell snap-in that includes the invoke-apartment cmdlet.";
}
}
}
}