Author Posts

February 25, 2018 at 3:52 am

I am using PowerShell to extract data from a series of Excel files, but I also need to use Excel and have other files open while running this PowerShell script and if I run my script, I end up killing the foreground Excel processes that I'm using as well as the one that PowerShell created. Sometimes the the background session that I'm trying to kill with these various suggestions remains open and the suggestions end up killing one of the foreground sessions.

I've tried unsuccessfully using variations of ideas similar to these two suggestions:
Really Kill that Excel Object
PSTip# Start a process and get its PID using Powershell

Any thoughts as to how to properly start an Excel session, identify its process id and only kill that one?

February 26, 2018 at 7:22 am

I haven't been able to test this fully but in using Excel 2016 it doesn't look like you get unique instances of the Excel.exe process, even if you start once instance as yourself and one using run as administrator, however if you can run the script under a different account it may work. If you can't isolate the excel process it doesn't look to good.

My home Windows 10 machine using two different accounts (both Microsoft accounts) it seems to launch ok but didn't get a separate instance. My thinking is if you get the separate instance you can then use basic get-process commands and work through things.

February 26, 2018 at 4:00 pm

I should have mentioned this previously, but I open every document in a separate instance of Excel. This was done with a setting in the registry but you can also Alt-click the taskbar icon to start a separate session if you don't use the registry.

Instruction for enabling this in the registry can be found here:
Excel to open in a new instance by default

The links I listed in my previous post sometimes work and sometimes don't. The problem is with the inconsistency of these particular options. My hope is that someone knows a way to initiate the line of code and capture the PID of that session so we can use it later to kill just that one process. The line to launch Excel is:

New-Object -ComObject Excel.Application

February 27, 2018 at 4:05 am

Ok, now that we have unique processes and such it gets a little easier, I got two different excel processes running and then used Get-Process & MainWindowTitle to distinguish between them, I then got a 3rd instance running use your ComObject command so now we have this:

get-process excel | select MainWindowTitle, Id, StartTime | Sort StartTime

MainWindowTitle Id StartTime
————— — ———
Book1 – Excel 2948 2/26/2018 7:37:03 PM
Book2 – Excel 16904 2/26/2018 7:37:23 PM
14024 2/26/2018 8:34:42 PM

(note: there is no MainWindowTitle for the ComObject in my test)

Without knowing everything you are doing, you should be able to launch an instance of Excel, get all Excel PIDs & sort by the StartTime so the last or first (if using Desc) PID is the newest process so it should be the one you want to end once whatever you are doing is done.

Something like this:

((get-process excel | select MainWindowTitle, ID, StartTime | Sort StartTime)[-1]).Id

PS C:\> 14024

Make sure you create a variable for each instance you are creating to keep things easier, possibly $E_FunctionName so at the end it is just a simple:

Stop-Process -Id 14024

or

Stop-Process -Id $E_FunctionName

Depending on how long things run etc, you could get the PID of any running instance at the beginning of the script (i.e. these should be your non script instances) so you can exclude those from any commands to end processes, likewise you could add the script related PIDs to a variable and track what PIDs the script has launched so at the very end you can ensure none of those PIDs are still active.

Sample:

$PIDs = @(14024, 2000, 18064,2948)
Get-Process -Id $PIDs -ErrorAction SilentlyContinue

Handles NPM(K) PM(K) WS(K) CPU(s) Id SI ProcessName
——- —— —– —– —— — — ———–
1241 107 120324 109864 19.33 2948 1 EXCEL

Am I getting close to what you need?

February 27, 2018 at 7:13 am

This works just as I hoped it would, many thanks. I use a loop to open dozens of files and it uses only the single instance it starts at the beginning so I don't need to keep tracking the last one.

I tried running my script against a subset of the files I need to open and close, and it didn't affect any of the other sessions I had open at the time of the script. I was even able to open new sessions after the script was started and these too did not close so I couldn't be happier.

I'm going to let it run overnight against all the files and see how things pan out, but at this point, I don't see an issue.

Thanks again, I really appreciate the help!

February 28, 2018 at 6:53 am

Great to hear we got it figured out, hopefully it makes for a nice time saver for you. I saw some overly complex but maybe elegant solutions for get PIDs for the Com-Object and stuff, sometimes keeping things simple can be way better.