I tend to leave my computer on for weeks at a time. The only issue I have with this is that the task bar flakes out after a number of days. Usually this takes the form of not rendering icons in the start menu. It can go as far as just not rendering anything in the start menu. Restarting the Explorer process works well to fix this in Windows 10.
Rather than manually trying to figure out which one of the explorer.exe
tasks is handling the task bar and restarting it, I'd like to write a powershell script that does this.
How would I programmatically determine which instance of explorer.exe
is currently responsible for the task bar?
A slightly more concise alternative to veefu's helpful answer:
Note: Similarly, no guarantees:
The method relies on the .MainWindowTitle
property of the taskbar-owning File Explorer instance reflecting the taskbar's window title, which happens to be empty, unlike the title of actual File Explorer windows - this appears to be the case on at least Windows 10 and Windows 7 (haven't tried others):
Get-Process explorer | ? MainWindowTitle -eq '' # returns taskbar-owning Explorer process
If other users could be logged on and you must limit the processes inspected to the current user's, run the following from an elevated console:
Get-Process -IncludeUserName explorer |
? MainWindowTitle -eq '' |
? UserName -eq (whoami)
Robust, but more complex approach:
Using Add-Member -MemberDefinition
, you can define a helper type and method that finds the handle (HWND) of the process that owns the taskbar window, utilizing a P/Invoke signature to call a Windows API functions; note that you'll incur an on-demand compilation performance penalty the first time you call this in a session.Tip of the hat to Klaidonis for helping me simplify the code.
# Define a helper type and method for getting a window's handle
# (HWND) by its class name and title.
$helperType = Add-Type -PassThru -Name "WinApiHelper$PID" -MemberDefinition @'
[DllImport("user32.dll", SetLastError=true)]
public static extern IntPtr FindWindow(string lpszClass, string lpszWindow);
'@
# Locate the explorer.exe process that created the taskbar,
# via window class "Shell_TrayHwnd" and an empty title.
Get-Process explorer |
? MainWindowHandle -eq ($helperType::FindWindow("Shell_TrayWnd", ''))
As for when multiple File Explorer processes may exist (based on trial and error - do tell me if I got things wrong):
If multiple users are logged on interactively (whether remotely or not), each such user may have one or more Explorer processes running, as described below.
An interactively logged-on user has at least one Explorer process, which owns the taskbar and the desktop - it may or may not have actual File Explorer windows open; let's call it the Explorer shell process.
If File Explorer's Launch folder windows in a separate process
view option is:
OFF (the default): all windows you create interactively are owned by the Explorer shell process - no new process is created.
ON: the first window you create interactively spawns one new Explorer process and all subsequently opened windows are then owned by that same new process.
In other words: If you only ever open File Explorer windows interactively, you either have one (Launch folder windows in a separate process
OFF) or up to two (Launch folder windows in a separate process
ON) Explorer processes.
If you create Explorer windows programmatically, it is a different story - see next point.
Irrespective of the Launch folder windows in a separate process
view setting, new Explorer processes can be created programmatically:
explorer /e,c:\
creates a new Explorer process every time.Note, the Folder Option 'Launch folder window in separate process' seems to be the setting that causes multiple explorer processes to be spawned. If this isn't set, it looks like there is only ever one Explorer.exe process.
It looks to me like every spawned explorer window beyond the first has a command-line including a '/factory' parameter, whereas the process that 'owns' the taskbar does not:
Get-WmiObject -Class Win32_process -Filter "name='Explorer.exe'" |
Select-Object ProcessID,CommandLine
ProcessID CommandLine --------- ----------- 3140 C:\WINDOWS\explorer.exe /factory,{ceff45ee-c862-41de-aee2-a022c81eda92} -Embedding 2068 C:\WINDOWS\explorer.exe /factory,{682159d9-c321-47ca-b3f1-30e36b2ec8b9} -Embedding 12164 "C:\WINDOWS\explorer.exe"
I tested by stopping the process that did have the taskbar, then spawning more explorer windows from an existing one. New explorer processes, having the /factory argument, did not re-create the taskbar.
Try finding explorer processes whose command-line don't contain /factory
:
Get-WmiObject -Class Win32_process -Filter "name='Explorer.exe'" |
Select-Object ProcessID,CommandLine |
Where-Object Commandline -NotLike "*/factory*"
No guarantees, but it's a path of exploration for you.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With