I'm doing an invoke-expression of an old console command written in C and I don't have control over the C source code... But, I think it's trapping the Ctrl-C to prevent the command line from interrupting it... Thus, when I invoke-expression from my powershell script there's no way to break the execution using ctrl-C and it locks my terminal and I need to keep killing and restarting my terminal window... which is super annoying...
Is there a way to make sure that powershell gets the ctrl-C instead of the C program when starting the C program using invoke-expression? Like maybe, I can refuse to give stdin to the C program, and let powershell have it instead? or maybe there's some solution where stdin goes to a different powershell thread that waits for a ctrl-c and then kills the invoke-expression thread..
Example:
PS> $cmd = <path_to_misbehaving_cpp_program_that_doesnt_Allow_ctrl_c_To_break_it>
PS> invoke-expression $cmd
# now here if I ctrl-C I can't break out of the invoke-expression....
# But I need this capability to ctrl-C
# to break the script and terminate the
# invoke expression of the C program.
CodePudding user response:
Starting and stopping (killing) a process from within powershell:
Use the Start-Process
cmdlet to start the other program. If you use the -PassThru
switch you get back the information witch process was started.
$Proc = Start-Process powershell.exe -ArgumentList '-command "sleep 60" ' -PassThru
This process can easily be killed with Stop-Process
even if it is supposed to run another 60 seconds:
$Proc | Stop-Process
Edit:
Now with exit code (Thx @mklement0 for the Wait
)
$Proc.WaitForExit()
$Proc.ExitCode
CodePudding user response:
The trick to get it to respond to ctrl-c was to pipe $null into the command run via start-process powershell... see below... Also, note at the end the finally "kill -force" kills the remaining child processes from the initial powershell.exe process-start... my program created childprocesses that keep running after the ctrl-c kill powershell.exe so i need to kill again...to kill the entire process tree.
$script:Proc = $null
# Run Command as a separate process
function x1_process {
write-host "`nx1_process: $args"
$posh = (get-command powershell.exe).Source
$iproc = Start-Process $posh -ArgumentList "`$null `| $args" -PassThru -NoNewWindow
$script:Proc = $iproc
if ($iproc -eq $null) {
throw "null proc"
}
Wait-Process -InputObject $iproc
$code = $iproc.ExitCode
if ($code -ne 0) {
throw "return-code:$code"
}
write-host "ok`n"
return
}
try {
x1_process mycommand.exe arg1 arg2 ...
}
finally {
if ($script:Proc) {
if (-not $script:Proc.HasExited) {
write-host -ForegroundColor Red "=> Killing X1_PROCESS <="
Stop-Process -InputObject $script:Proc -Force -ErrorAction SilentlyContinue
}
}
}