Can Start-Process start a process and let it run even when script ends in TFS? - windows

I'm using Start-Process cmdlet as part of a Powershell script being executed by the new scriptable TFS build system.
My issue is that I'm starting some executables from my Powershell script and once the build step ends, it kills started processes.
I've also also tried to use ProcessStartInfo directly and Start-Job with no luck.
When I run that script alone it ends, but it leaves the started processes opened.
Is there any way to solve this?

You can use start-Job:
Start-Job -ScriptBlock { start C:\Windows\notepad.exe }
After exiting the PS, Notepad is still open
Check this post for more info:
if you start a script using Start-Process, it will survive the shell
termination, but if you started it from a console window then it stays
bound to that window and closing the window will terminate the process

Related

Starting a background process on Windows through an SSH connection that doesn't get stopped when SSH disconnects

I have a java application that I'm trying to deploy to a Windows server via SSH (via Jenkins). I wrote a powershell script to start the process in the background using start-process and javaw:
$SSL_KEYSTORE_PASSWORD = $args[0]
Write-Output "Running war in the background"
Start-Process javaw -ArgumentList "-jar", `
"e:\app\app.war", `
$("-Dserver.ssl.key-store-password=" + $SSL_KEYSTORE_PASSWORD), `
"-Dserver.tomcat.basedir=e:\app" `
-RedirectStandardOutput "e:\app\output\stdout.txt" `
-RedirectStandardError "e:\app\output\stderr.txt"
Write-Output "Starting javaw instance"
When I run the script from the server, it works perfectly: the process runs in the background indefinitely and all the output goes to the right place. But, when I attempt to run it via SSH from jenkins, the java application will start up properly, but as soon as the powershell script ends, the process gets killed. Initially, I thought it was jenkins killing the process, but I did some debugging and figured out that it's getting killed as soon as it exits the powershell script, so I think it's related to SSH. This is the line in the jenkinsfile that's attempting to start up the process:
sh 'ssh -o StrictHostKeyChecking=no $ssh_target powershell e:\\app\\startup $SSL_KEYSTORE_PASSWORD'
I would like to start the process using a powershell script like this, because once I get this working, I'd like to add some other stuff into the powershell script to make sure it started up properly, and I don't want to clutter up the jenkinsfile even more than it already is.

How to start long-running/background process from PowerShell completion mechanism?

I have a PowerShell completion hook that looks like:
$scriptblock = {
param($wordToComplete, $commandAst, $cursorPosition)
# ...
clap-json-test-completions power-shell query $wordToComplete $script:index -- #elements | ForEach-Object {
[System.Management.Automation.CompletionResult]::new($_)
}
}
Register-ArgumentCompleter -Native -CommandName clap-json-test -ScriptBlock $scriptblock
The clap-json-test-completions command is a program written in Rust which generates suggestions for the completing the current command line.
The clap-json-test-completions program is designed to talk to a local "server" process on the machine for certain bits of information that take longer to figure out and can be cached by the server process. If the server process isn't running then the clap-json-test-completions program attempts to start it up.
Unfortunately, the PowerShell completions mechanism waits until that server process stops before returning the suggestions to the user. As that server process is designed to not stop, this is an issue.
I have tried spawning the server process using:
.creation_flags(
DETACHED_PROCESS_FLAG
| CREATE_NEW_PROCESS_GROUP_FLAG
)
Based on the Creation Flags documentation in the Windows docs. Unfortunately they don't seem to have to desired effect. Instead of allowing the completion process to return whilst the server is still running, they just seem to make it so that Ctrl-C no longer kills the server from the hung completion prompt.
I've also tried launching the command a "Job" using:
Start-Job -ScriptBlock { clap-json-test-completions power-shell query $wordToComplete $script:index -- #elements } | Receive-Job -AutoRemoveJob -Wait | ForEach-Object {
[System.Management.Automation.CompletionResult]::new($_)
}
In the Power-Shell completion script and using CREATE_BREAKAWAY_FROM_JOB_FLAG as an additional creation flag but that doesn't seem to work.
I understand that Windows Services exist for long running processes but we would rather have a situation where the server only starts when the user first tries to do a completion and have a situation where the user has permissions to start the server (as a normal process) rather than requiring extra permissions to interact with the Windows Service system.
The current approach works fine if the clap-json-test-completions binary is run by itself outside of the completions system. It doesn't hang waiting for the server to finish.
Is there an approach to either the PowerShell completion script or the process creation in the Rust code that'll allow the completion system to return whilst the server still runs?

How do I kill a process in Powershell

Say I'm running a python script that doesn't exit properly. The powershell console does not return control to me without having to close the shell and open a new one. With Bash I can simply press Control-C to kill any process. What am I missing here?
Windows 8.1 Powershell
To kill a process, you can use the command Stop-Process.
Or you can try Ctrl + Break shortcut.
Use the following stop-service <service> choose a flag like -force to force stop even if it has dependent services as well.
https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.management/stop-service?view=powershell-5.1

remote execution(PowerShell) of cmd file doesn't complete

Current PS script:
Invoke-Command -ComputerName RemoteServer007.FQDN.com -ScriptBlock {
Set-Variable -Name WOWCONFIG -value "d:\ABCs\WOWzers" `
| Start-Process "d:\da-folder\Do-It-NOW-Pleez.cmd"
}
If I log on locally to the server(RemoteServer007.FQDN.com) and execute the cmd file, it runs through all of the lines(commands) within the cmd file.
When I execute it remotely, it gets about 30% of the way through the commands within the cmd file, the PS execution ends without error, but not all of the lines/commands in the cmd file had been executed.
This was discovered by simply configuring each line of the cmd file to output to txt files.
I even tried re-ranging the commands in the cmd file, thinking that perhaps there was a specific command that was causing it to exit, but that is not the case.
I'm wondering if there is some timeout or response that PowerShell is not getting? and just quitting almost immediately after starting?
Any ideas or help would be greatly appreciated.
There are a couple of things you can do here:
You may have a memory issue. Increasing the value of MaxMemoryPerShellMB might help
set-item WSMan:\$target\Shell\MaxMemoryPerShellMB -Value 0 -Force
You'd need to run this once on the remote machine before you execute your commands again.
You can also see possible error logs in the windows event viewer. There are categories for powershell and for Windows Remote Management which you should look at.
Finally, you can just run this process asynchronously, using the task scheduler for instance. I had a similar problem with windows in the past, and running the process from the task scheduler, outside the powershell session, fixed it. There's an example of how we did this in Cloudify here:
https://github.com/CloudifySource/cloudify/blob/master/esc/src/main/resources/clouds/ec2-win/upload/bootstrap-management.ps1#L220

kill remote job initiated by invoke-command

what is the easy way to kill remote job initiated by invoke-command with background processes?
I kick remote PS script to run legacy exe file and need a way to kill that process.
I was going to use stop-job first but as I am reading it works only for local processes.
Then I was going to use Remove-job -force command but if I understood right, it cannot kill running process until it completes (again my remote ps script will start another process to run exe file).
I am reading I can kill a process using wmi terminate command but I do not know how to get PID of remote process (I cannot use name because I can kill processes from other users)
what is the best way to achieve my goal?
my script looks like that:
invoke-command -computername server1,server2,server3..etc -script-block {my.exe} -asjob
loop to wait for all processes to complete and report progress
check for CTRL-C press and kill all remote instances on {my.exe}
ok checked this morning from work and this works fine from a calling script:
get-job | remove-job -force
I was confused by MSDN doc which says:
When you stop a background job, Windows PowerShell **completes** all tasks that are pending in that job queue and then ends the job
Check out this answer, you can add the start process command to your script block and return the pid or save it to a text file to be reference later.
PowerShell - get process ID of called application

Resources