0

I need to access underlying powershell default Pipeline which just created as result of Pwoershell.Create(); I need to stop that pipeline so that script execution must stopped immediately.

I know I can Create Pipeline object and execute script by calling pipeline.Invoke(). But Pipeline object not giving me all Data streams which is being provided by Powershell instance.

powerShellInstance = PowerShell.Create();
powerShellInstance.Runspace = RunspaceFactory.CreateRunspace(iss)

Later some point I need

powerShellInstance.GetPipeline().Stop()  // something like this.

Is there any thing by which I can achieve this?

Edit

For example I have following script.

Set-LinkParameter"withError"  => This commandlet will throw error
Set-LinkParameter11 "Mistyped" "error" => Powershell will throw an error of invalid commandlet

Initialiize-Access  => this is invalid here and this commandlet will throw error.  Here it must not allow further script to execute.

Write-Host "This is test message for host"
Write-Information "test information"

Write-Error "Access denied."  --> this is can be terminating error ( depends)
Write-Warning "This is test warning." 
Write-Verbose "This is verbose message"
Write-Verbose "This is verbose message" -Verbose

Write-Debug "Test Debug message" -Debug
Write-Debug "wont appear at debug pipeline"

Write-Output @(1,2,3) -NoEnumerate | measure

Edit (Async Stop) before in the code..

powerShellInstance.Streams.Error.DataAdded += OnError

OnError(sender,event)
{
   //this would have been invoked asyncronously. 
   powerShellInstance.BeginStop(null,null);
}
Usman
  • 2,742
  • 4
  • 44
  • 82
  • The `PowerShell` class also has a `Stop` method, have you tried that? – Patrick Meinecke Jul 19 '18 at 21:11
  • I used that inside Error handler which is subscribed to log an error and terminate from there. But it somehow hangs the whole powershell execution and doesn't return back. – Usman Jul 19 '18 at 21:31
  • I think, at Stop call, it should terminate currently executing pipeline and closing the run space. – Usman Jul 19 '18 at 21:38
  • If the command that is currently running when `Stop` is called is blocking and does not implement `StopProcessing` then there is no way to cancel the command. This is most common when invoking methods directly in PowerShell, but some compiled commands may fail to stop as well. There's no way to guarantee the cancellation of the pipeline other than terminating the process. – Patrick Meinecke Jul 19 '18 at 21:55
  • Then what should be the ideal way to stop the powershell script execution when i catch first error. I used BeginStop, and it seemed working. Because, it calls asynchronous method with IAsyncResult and state. – Usman Jul 19 '18 at 21:59
  • I'm not sure what you mean by when you catch first error. If you mean when the PowerShell script hits an error, you can set the `ErrorActionPreference` by creating an instance of `PSInvocationSettings` and passing it to `PowerShell.Invoke`. If that isn't what you mean, can you update your question with a more full example of what you're trying to do? – Patrick Meinecke Jul 19 '18 at 22:13
  • I edited the post above and added script. In that script I want to terminate the whole execution of script if certain commandlet throws error. ( as you can see Initialize..) For some commandlets I dont want to terminate the script processing but want to log those errors. That's what I want to achieve. Somewhere I want to achieve strict type checking and termination of script in case for others I might want to continue and want to log them all together. – Usman Jul 20 '18 at 07:25

1 Answers1

0

The direct answer to your original question is, unfortunately you cannot. There is no publicly accessible way to obtain the currently running pipeline, either via the PowerShell class or otherwise. The only way to interact with Pipeline is to create it via Runspace.CreatePipeline. Additionally, the Pipeline API is not available in PowerShell Standard and will eventually be removed.

The answer to your revised question of (paraphrased) "How do I terminate a PowerShell script invoked via the PowerShell class after an error" is to use PowerShell.Stop()

However, as you have noticed that does not guarantee termination. The reason for this is because by the time your event fires and you call PowerShell.Stop(), the PowerShell script has likely already moved on to the next sequence point. If that next sequence point is a method invocation that blocks, or a cmdlet that does not implement Cmdlet.StopProcessing then the pipeline will not stop until that is finished. If it never finishes then PowerShell.Stop never finishes. There's no way around it other than killing the process.

Patrick Meinecke
  • 3,963
  • 2
  • 18
  • 26
  • What about Stopping as async manner . Which i tried and seemed to be working. I need sugetions whether it is a safe approach? – Usman Jul 21 '18 at 08:21