Script to kill started application - powershell

I am looking to:
delete the contents of a folder
run an application
then put in a Kill command (Stop-Process) if it runs longer than a specified period of time.
But I'm not sure where to start. Any suggestions?

If you are starting the application from a PowerShell script, and waiting in that script... then you just need a way to keep track of time in your script before calling Stop-Process. You'll also need to be sure you know what process you are going to kill.
A simple implementation could use Start-Sleep in a loop:
$pid = PID OF THE RUNNING APPLICATION
$iter = 0
while((Get-Process -Id $pid)){
$iter++
Start-Sleep -Seconds 1
if($iter -gt 60) {
Stop-Process -Id $pid
break
}
}
If your process was started elsewhere you might need to pull the process start time. This doesn't seem to be returned by Get-Process so you might want to try a WMI query:
Get-WmiObject -Class Win32_Process -Filter "Name = 'APP.exe'"-Property Name,CreationDate
You can then look for instances of APP.exe that started before a certain time.

Before you try to delete an item (folder/file) check it exists:
$folder = "C:\folder"
if (Test-Path $folder) { Remove-Item $folder -Recurse }
Stop process if it's been running for 30mins:
Get-Process firefox | Where StartTime -lt (Get-Date).AddMinutes(-30) | Stop-Process -Force

Related

Powershell Stop-Process Many Instances

I have a remote access program that does not clean up after itself after it is closed. In Task Manager, I oftentimes find 5 to 10 instances of the program running. For instance:
XYZ.exe
XYZ.exe
XYZ.exe
XYZ.exe
XYZ.exe
I have a simple Powershell script to stop these processes, but the problem is I want to close n-1 out of n processes.
> Stop-Process -Force -Name XYZ*
kills n out of n processes.
Is there a way to kill all processes of a program while leaving open the newest (e.g. XYZ.exe #5)?
Use Get-Process to discover all matching processes ahead of time, then simply remove one of them before killing the rest:
Get-Process -Name XYZ* |Select -Skip 1 |Stop-Process -Force
Try this: it closes all non responding processes
Get-Process -name XYZ.exe| Where-Object -FilterScript {$_.Responding -eq $false} | Stop-Process

How can I start a process, pause for 2 hours and then kill a process in Powershell

How can I start a process, pause for 2 hours and then kill a process in Powershell. I can get it to launch the process and kill the process but the Start-Sleep command doesn't seem to be working in my script. I thought this would be simple. Not sure if I'm missing something or if this is even possible to sleep for 2 hours.
if((Get-Process -Name test -ErrorAction SilentlyContinue) -eq $null){
."C:\Program Files (x86)\test.exe" Start-Sleep -s 7200 Stop-Process -name test}
just to add something to Jeff's answer - you can use Start-Process and -PassThru to make sure you're ending the correct process that you launched.
if ((Get-Process 'test' -EA SilentlyContinue) -eq $null){
$Process = Start-Process "C:\Program Files (x86)\test.exe" -PassThru
Start-Sleep -Seconds (2*60*60)
$Process | Stop-Process
}
this will mean that if the process dies for another reason and is relaunched manually or by another copy of the script etc, that this script won't just kill it after two hours, but will kill the correct process.
When you are placing multiple PowerShell commands in a single-line script block, you must separate the commands with semicolons:
if((Get-Process -Name test -ErrorAction SilentlyContinue) -eq $null){ ."C:\Program Files (x86)\test.exe" ; Start-Sleep -s 7200 ; Stop-Process -name test}

Wait for an Active Directory query to finish before executing next line

Trying to work out how I can make the below code:
Wait for line 1 to complete before continuing.
Wait for line 4 to complete before running line 5
.
$invokevar = Get-ADComputer -Filter * -SearchBase $searchbase | select -Expand dnshostname
New-Variable -name "invoke$dom" -value $invokevar -Force
$fullvar = Get-Variable -Name "invoke$dom" -ValueOnly
$results = Invoke-Command -ComputerName $fullvar -ScriptBlock $sbmain
$badhosts = Compare-Object $($invokevar | Sort-Object) $($results | select -expand pscomputername | Sort-Object) | select -expand InputObject
Having a mental block, any help would be appreciated.
In powershell, the script executes line by line
Unless or until the execution of line 1 finishes, the script wont go for line 2.
So ideally you shouldn't be worrying about the problem stated above.
For internal commands PowerShell does wait before starting the next command. One exception to this rule is external Windows subsystem based EXE applications, you can apply out-null
PowerShell will wait until the exe process has been exited before continuing.
You can also use Start-Process with the -Wait parameter:
Start-Process <path to exe> -NoNewWindow -Wait
If you are using the PowerShell Community Extensions version it is:
$proc = Start-Process <path to exe> -NoWindow
$proc.WaitForExit()
Another option in PowerShell 2.0 is to use a background job:
$job = Start-Job { invoke command here }
Wait-Job $job
Receive-Job $job
In your case it will wait for the execution to get completed. Else you can check the status using a do-While loop and keep on adding a start-sleep of 1 sec
Hope this approach helps you.
Those answers are wrong. Get-ADUser absolutely may return data in the middle of the script down the line..
Some get-aduser command
echo "some string"
I have seen output line 2 first and then the results from line 1.
The only way around this is to assign a variable to the query and process the variable.
$string = get-aduser....
process $string
echo "some string"
This will process in order 1,2,3 without failure.

Count number of scripts running and wait for them to finish

I'm looking for the best way to count the number of PowerShell scripts that are currently running.
I run .ps1 scripts from windows batch files. The script I am working on now is launched when a particular email is received from a client - but I want this script to first of all check that no other scripts are busy running at the moment, and if they are it must wait for them to finish before it continues.
I'm sure there are a few ways to go about this, but what would be the safest? I am still learning.
If it is possible to move away from batch files to launch PowerShell then I would suggest using Start-Process to launch your scripts. This will allow you to wait for your processes to exit using where-object and Measure-Object to filter the scripts that have not yet completed.
So your script might look something like this:
# create a loop
foreach ($item in $reasontoloop) {
$arguments = "define script names and arguments"
# Start the powershell script
$procs += Start-Process powershell -PassThru -argumentlist $arguments
}
Write-Host -message "Waiting for Processes to complete"
while( $procs | Where-Object { $_.hasExited -eq $false } )
{
# Display progress
$measureInfo = $procs | Where-Object { $_.hasExited -eq $true } | Measure-Object
write-host "$($measureInfo.count) of $($procs.Length) still running"
Start-Sleep 1
}
Write-Host -message "Processes complete"
If you are simply interested in the number of PowerShell instances executing then the following one liner using Get-Process will help.
#(Get-Process | where-object {$_.ProcessName -like 'powershell'}).count

Kill process by filename

I have 3 instances of application running from different places. All processes have similar names.
How can I kill process that was launched from specific place?
You can get the application path:
Get-Process | Where-Object {$_.Path -like "*something*"} | Stop-Process -WhatIf
That will work for the local machine only. To terminate remote processes:
Get-WmiObject Win32_Process -Filter "ExecutablePath LIKE '%something%'" -ComputerName server1 | Invoke-WmiMethod -Name Terminate
I would like to slightly improve Shay Levy's answer, as it didn't work work well on my setup (version 4 of powershell)
Get-Process | Where-Object {$_.Path -like "*something*"} | Stop-Process -Force -processname {$_.ProcessName}
You can take a look at the MainModule property inside of the Process class (which can be invoked via powershell).
foreach (Process process in Process.GetProcesses())
{
if (process.MainModule.FileName == location)
{
process.Kill();
}
}
I'd also consider the possible exceptions that can occur while calling this code. This might occur if you're trying to access processes that are no longer present (killed since the last time GetProcess was called) or processes for while you do not have permissions.
Try this:
http://technet.microsoft.com/en-us/library/ee177004.aspx
Stop-Process -processname notepad
The below command kills processes wherein "something" is part of the path or is a command line parameter. It also proves useful for terminating powershell scripts such as powershell -command c:\my-place\something.ps1 running something.ps1 from place c:\my-place:
gwmi win32_process | Where-Object {$_.CommandLine -like "*something*"} | % { "$(Stop-Process $_.ProcessID)" }
The solution works locally on my 64bit Windows 10 machine.