Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Find which explorer.exe is controlling the taskbar?

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?

like image 279
Ouroborus Avatar asked Dec 13 '22 18:12

Ouroborus


2 Answers

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:

    • For instance, a command such as explorer /e,c:\ creates a new Explorer process every time.
like image 119
mklement0 Avatar answered Dec 29 '22 23:12

mklement0


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.

like image 20
veefu Avatar answered Dec 29 '22 22:12

veefu