I have written an PowerShell CmdLet with C#. Within this class I want to be able to execute other PowerShell Scripts in the same instance.
I've tried different ways, but nothing is working....
Thank you
...
[Cmdlet(VerbsCommon.Show, "XamlWindow")]
public class ShowXamlWindowPS : PSCmdlet {
[Parameter(Mandatory = true, ValueFromPipelineByPropertyName = true, ValueFromPipeline = true, ParameterSetName = "FromXml")]
public XmlDocument Xml { private get; set; }
/// ...
protected override void ProcessRecord() {
XmlNodeReader reader = null;
switch (this.ParameterSetName) {
case "FromXml": {
reader =new (Xml);
break;
}
case "FromString": {
XmlDocument xml =new ();
xml.LoadXml(Xaml);
reader = new XmlNodeReader(xml);
break;
}
case "FromFile": {
XmlDocument xml = new();
xml.Load(this.Path.FullName);
reader = new XmlNodeReader(xml);
break;
}
}
var host = (System.Management.Automation.Host.PSHost)SessionState.PSVariable.GetValue("Host");
PowerShell ps = PowerShell.Create();
ps.Runspace = Runspace.DefaultRunspace;
// script to providing a new function in the PS instance
string script = "function Test-Function1{";
script += "Get-Process";
script += "}";
ps.AddStatement().AddScript(script).Invoke(); // does not work, pipeline is busy within the default runspace
var t = XamlReader.Load(reader);
WriteObject(t);
}
}
I looking for a solution to access the calling Powershell instance.
In a PSCmdlet
-derived cmdlet implementation, SessionState.InvokeCommand.InvokeScript()
allows you to invoke arbitrary commands in the current runspace (albeit in a new pipeline)
The following simplified example in PowerShell code (which uses the automatic $PSCmdlet
variable) demonstrates this:
1..2 | ForEach-Object {
# This script block with a [CmdletBinding()] parameter is the equivalent
# of a PSCmdlet-derived C# class implementation.
& {
[CmdletBinding()] param()
# Pass an arbitrary snippet of PowerShell code to .InvokeScript(),
# which may include calls to script files.
$PSCmdlet.SessionState.InvokeCommand.InvokeScript("Write-Output $_")
}
}