Kill a task based on its windows title - powershell

I'm looking to kill a process using it PID when a particular file is open on my computer, so that it doesn't interfere with another script
I have an excel sheet that is referenced by other parts of my system, it is fed information from many different sources I want to automate my workflow to work more smoothly.
Get-Process |where {$_.mainWindowTItle -eq "RASP transfer.xlsx - Excel"} |Write-Output
I'm stuck on how to extract the PID and use it as a variable in a task Stop-Process -ID PID
maybe I'm missing something help
in the end it should look something like this
Get-Process |
Where {$_.mainWindowTItle -eq "RASP transfer.xlsx - Excel"} |
Write-Output $pid=id |
Stop-Process -ID $PID
edit: 6/6/19
Currently I'm able to identify the PID of the specific workbook
by running
Get-Process |where {$_.mainWindowTItle -eq "RASP transfer.xlsx - Excel"} |Write-Output
which I can identify here in the taskmanager
However when the files are run with scripts the excel file is hidden and can't be searched with the windows title....

One of the nice features of Powershell is that you can pass an object on the pipeline. You don't even need the Process ID:
Get-Process | Where {$_.mainWindowTItle -eq "RASP transfer.xlsx - Excel"} | Stop-Process
However it's important to know what type of object you're passing along at each stage in the pipeline. The input to Stop-Process in the line above is a Process object, that has an ID property.
If you wanted to get the Process ID you could assign it to a variable.
$PID = (Get-Process | Where {$_.mainWindowTItle -eq "RASP transfer.xlsx - Excel"}).ID
... which will usually only get a single Process ID because Excel doesn't allow opening the same spreadsheet in two windows. But you can't rely on the window title to be unique because it would be the same if you opened two copies of the same spreadsheet from different folders.
If you wanted to close all Excel windows, this code would get all the Excel windows' processes into an Object[] array:
$ExcelProcs = Get-Process | Where {$_.mainWindowTItle -like "* - Excel"}
Stop-Process is smart enough to use the array of [Object] as input and stop all their processes:
$ExcelProcs | Stop-Process

Why not just re- enable the visibility before you check for the open sheet with:
$x1.Visible = $true
$PID = (Get-Process | Where {$_.mainWindowTItle -eq "RASP transfer.xlsx - Excel"}).ID

Related

Powershell script to compare processes from text file

I need to do the following:
Get a list of all the current processes on the system and save them to a text file called “before.txt”
Launch a new browser window (Chrome, Edge, Firefox – your choice)
Get a new list of all the current processes on the system and save them to a text file called “after.txt”
Using the compare-object cmdlet in PowerShell, find the new process ID for the browser you just opened
Once the process ID has been identified, kill the process using that process ID
I'm having difficulty completing the last task of killing the identified process from the text file. Any help is greatly appreciated. Thank you!
########################## Current Script#########################
Get-Process | select-object -Expand Name > before.txt
Invoke-Item "C:\Program Files\Internet Explorer\iexplore.exe"
Start-Sleep -s 3
Get-Process | select-object -Expand Name > after.txt
Compare-Object (get-content before.txt) (Get-Content after.txt) > final.text
$list = Get-Content final.text; Get-Process $list | kill -force -Raw
The simple fix to your code is to change the compare-object line. Try running that line without the redirect and you'll see it's not a simple list of names. Try changing that line in your script to the following:
Compare-Object (get-content before.txt) (Get-Content after.txt) | select -ExpandProperty InputObject > final.text
However, in PowerShell you don't need to use all these temporary files. You can have arrays of items. A more PowerShell answer would be:
$before = Get-Process
Invoke-Item ...
$after = Get-Process
$list = Compare-Object $before $after
$list |% { stop-process $_.InputObject.id }

Powershell close multiple windows / end processes based on name

I have a pretty neat mess of batch/python scripts that install a program called MATRIS, followed by about 15 exe updates.
Around 11 of these updates open a window telling me the that the update was successful.
Now it would be really fun to run a batch or powershell script which closes all of these windows for me.
The last thing I tried was Get-Process | Where-Object {$_.Path -like "MatrisInstaller.APCIPLUS"} | Stop-Process -WhatIf
I wasn't sure if it was the name as read in task manager, or like the title of the window, but I tried both.
Please note that a couple of these are (32 bit) - I'm not sure if that would impact the script.
I was able to run tasklist followed by kill {PID} but PIDs change: I'm not sure how to script it.
Please reply if you need any clarification, I've historically been poor at wording my questions.
In your example, Path is pointing to the executable file on disk, so while possible to use (if it is consistent), it won't match the name you find in the processes tab of Task Manager. Typically, people will use the name as shown on the Details tab of Task manager. For example, with Outlook on my system, these three possibilities are:
Path: C:\Program Files\Microsoft Office\Office16\OUTLOOK.EXE
Processes tab: Microsoft Outlook
Details tab: outlook.exe
So, you need a command like this:
Get-Process | Where Name -eq 'Outlook' | Stop-Process
or, better:
Get-Process -Name 'Outlook' | Stop-Process
Note that PowerShell expects you to remove the '.exe' you see in Task manager.
EDIT: Additional technique
If you know the names of the processes, then you can simplify your script by doing something like this:
$processList = "Process1","Process2","Process3" # Add all process names to the list
$processList |
ForEach-Object {
Get-Process -Name $_ | Stop-Process
}
You were almost there, just need to change "Path" to "ProcessName" like so:
Get-Process | Where-Object {$_.ProcessName -like "MatrisInstaller.APCIPLUS"} | Stop-Process -WhatIf

How to avoid powershell going into wait mode automatically

I have a powershell script which automates the upload of a report. After the file upload dialog box opens in Internet Explorer, My code tries to get it's id and then send keys and send the file address and sendkeys enter. But unfortunately as soon as the file upload dialog box pops up my script doesn't proceed further and waits there. If I hit close (in the file upload dialog) then the script continues. Is there any way by which I can tell powershell to not wait for anything?
Here's my code :-
$dummy = get-process iexplore | where {$_.mainWindowTitle -eq "ArkAngelWeb - Hitachi Systems Security Inc. - Internet Explorer"} | select -expand id
Sleep 1
$temp = $ie.Document.documentElement.getElementsByClassName("v-button-caption") | Where-Object {$_.innerHTML -eq "Select file"}
$temp.click()
Sleep 2
$swshell=New-Object -ComObject wscript.shell
$fileUploadDialog = get-process iexplore | where {$_.mainWindowTitle -eq "ArkAngelWeb - Hitachi Systems Security Inc. - Internet Explorer" -and $_.Id -ne
$dummy.Id} | select -expand id
$swshell.AppActivate($fileUploadDialog.Id)
$swshell.SendKeys("H");
$swshell.SendKeys("{TAB}")
$swshell.SendKeys("C:\Users\ratns1\Desktop\TEST_FILE.txt")
$swshell.SendKeys("~")
Thanks
This is the issue with SendKeys, timing, UI controls, etc.
You are popping a model dialog box, and that is what's causing the wait.
By design, your script will not continue until you dismiss it. This is the design for dialogs.
PoSH notwithstanding, it is your use case that is the catch 22, not PoSH itself.
Take a look at the Wasp module to take the load off all the sendkey and Window lookup stuff off your plate.
Occasionally, the only way of automating processes is to send
keystrokes or mouse clicks to UI elements. A good and free PowerShell
extension is called "WASP" and is available here:
http://wasp.codeplex.com/
Once you install the module (do not forget to unblock the ZIP file
before you unpack it, via right-click, Properties, Unblock), the WASP
module provides the following cmdlets:
Get-WindowPosition
Remove-Window
Select-ChildWindow
Select-Control
Select-Window
Send-Click
Send-Keys
Set-WindowsActive
Set-WindwowPosition
Here is a simple automation example using the Windows calculator:
Import-Module WASP
# launch Calculator
$process = Start-Process -FilePath calc -PassThru
$id = $process.Id
Start-Sleep -Seconds 2
$window = Select-Window | Where-Object { $_.ProcessID -eq $id }
# send keys
$window | Send-Keys 123
$window | Send-Keys '{+}'
$window | Send-Keys 999
$window | Send-Keys =
# send CTRL+c
$window | Send-Keys '^c'

Redirect powershell in batch file works to file but not to null

The following line of code (in a 'Administrator' cmd window on Windows 10) outputs the title of some open windows to the me.txt file, and not to the screen:
POWERSHELL "Get-Process | Where-Object {$_.MainWindowTitle -ne ''} | Select-Object MainWindowTitle" 1>C:\me.txt
But the following line outputs to the screen, even though I say don't:
POWERSHELL "Get-Process | Where-Object {$_.MainWindowTitle -ne ''} | Select-Object MainWindowTitle" 1>NUL
Any ideas?
And I know that there is no point to the command if I am not interested in the result...
[Update] The reason for doing this is because the first time the line is run, it takes almost a second longer than subsequent times, so I wanted to run it once up front to make subsequent times more consistent. In those subsequent runs I do look at the results :-)
Does this produce the expect result? Apologies cannot test as no admin
POWERSHELL "Get-Process | Where-Object {$_.MainWindowTitle -ne ''} | Select-Object MainWindowTitle | Out-Null"

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