0

I have a program that passes a command line to the explorer process to execute in the user's non-elevated desktop context. Part of doing that requires using IShellWindows::FindWindowSW to search for the desktop window, as can be seen in this ExecInExplorer example from the Windows 7 SDK.

If for some reason explorer is restarted (such as 'Exit Explorer' and restart [2]) and the old explorer doesn't actually exit then FindWindowSW returns S_FALSE for the desktop window. In this case the new explorer process owns the desktop and the old process (which should have terminated) does not. I suspect FindWindowSW is searching only the old explorer process.

If there are multiple explorers running is there any way to search all of them for IDispatch to the desktop?

#include <windows.h>
#include <shlwapi.h>
#include <shlobj.h>
#include <stdio.h>
#include <malloc.h>

#pragma comment(lib, "shlwapi.lib")


int main(int argc, char *argv[]) {
  (argv); (argc);
  init();
  
  HRESULT hr;
  IShellWindows *psw;
  
  hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE);
  if (SUCCEEDED(hr))
  {
    hr = CoCreateInstance(CLSID_ShellWindows, NULL, CLSCTX_LOCAL_SERVER, IID_PPV_ARGS(&psw));
    if (SUCCEEDED(hr))
    {
      HWND hwnd;
      IDispatch* pdisp;
      VARIANT vEmpty = {}; // VT_EMPTY
      HRESULT f = psw->FindWindowSW(&vEmpty, &vEmpty, SWC_DESKTOP, (long*)&hwnd, SWFO_NEEDDISPATCH, &pdisp);
      if(f == S_OK)
        printf("S_OK, hwnd: 0x%lx\n", *(long*)&hwnd);
      else if(f == S_FALSE)
        printf("S_FALSE\n");
      else
        printf("0x%lx\n", f);
    }
  }
  return 0;
}

[2]: (Sometimes when I am developing I will 'Exit Explorer' (Hold down CTRL+SHIFT and right-click on an empty part of the start menu) and then restart it from a command prompt. Occasionally explorer despite exiting (ie the taskbar disappears) doesn't actually terminate which means when I start explorer again then more than one explorer is running. The old explorer still running is not the separate process that can be used for displaying folders. I don't have a way to reproduce this, it seems arbitrary.)

Jay
  • 319
  • 3
  • 12
  • The multiple explorer process is an implementation detail, if the call fails, it means what you're looking for is not available (note: this code accesses a proxy, not explorer.exe directly) and indeed, sometimes explorer is gone until someones call explorer.exe explicitely. Are you sure it's not caused by a race condition? ie: have you tried to call FindWindowSW in some loop? – Simon Mourier Dec 29 '20 at 08:28
  • @SimonMourier No I haven't tried to call it in a loop, however I have run the sample program multiple times and it always returns S_FALSE. To remedy I can kill all explorer processes in Process Explorer and then start an explorer process from a non-elevated command prompt and it will work again. Maybe it is a Windows bug but I thought COM would just failover. – Jay Dec 29 '20 at 21:19
  • Aren't STA's required to run a message loop? – IInspectable Dec 29 '20 at 22:18
  • @IInspectable Technically yes STA requires a message loop to handle calls from other processes and apartments but that's not relevant here. – Jay Dec 29 '20 at 22:51
  • 1
    My experience is the "Exit Explorer" menu trick doesn't really restart explorer all the times. It only fully works if all explorer.exe instances can unload all the 3rd party dlls (shell extensions) they have loaded. If one is stuck for some reason, it just stays there and you'll have to kill them all and restart one. Don't think this qualifies as a bug but only Microsoft could tell you. – Simon Mourier Dec 30 '20 at 09:46

0 Answers0