WM_TIMER?

Charles Dye

Super Moderator
Staff member
May 20, 2008
3,609
46
Albuquerque, NM
prospero.unm.edu
#6
I recall doing something similar in PopupFix: start a timer, check the console window's visible/hidden status every n milliseconds. If it has changed from visible to hidden or vice versa, the console may have been attached or detached to Take Command/Console2/ConEmu, so do further checks for all of those and update internal variables....
 
#7
I recall doing something similar in PopupFix: start a timer, check the console window's visible/hidden status every n milliseconds. If it has changed from visible to hidden or vice versa, the console may have been attached or detached to Take Command/Console2/ConEmu, so do further checks for all of those and update internal variables....
I don't know about Rex's needs, but for yours, Charles, what's below, meant only as a test, works pretty well to tell if TCC has been attached/detached. Below, bInTab() expands L"%_TCTAB" and returns TRUE/FALSE accordingly.
Code:
VOID CALLBACK WinEventProc(HWINEVENTHOOK hWinEventHook, DWORD event, HWND hwnd, LONG idObject,
   LONG idChild, DWORD dwEventThread, DWORD dwmsEventTime)
{
   if ( hwnd == global.hWndConsole )
     Printf(L"%s a tab!\r\n", bInTab() ? L"In" : L"Not in");
}
// In InitializePlugin
  HWINEVENTHOOK hWinEvent = SetWinEventHook(EVENT_OBJECT_SHOW, EVENT_OBJECT_HIDE,
     global.hThisModule, WinEventProc, 0, 0, WINEVENT_OUTOFCONTEXT);
 
Likes: Charles Dye
#11
A P.S. on that. If you could figure out TCC's instance of conhost.exe, you could target that PID with the Win event hook rather than all processes (0). I tested that by watching a CMD be attached/detached using a Win event hook which targeted CMD's conhost. EVENT_OBJECT_SHOW and EVENT_OBJECT_HIDE are generated by the conhost process. I don't know how to get the PID of TCC's conhost ... Rex? ... Charles?
 
#12
This works nicely (in a plugin) to get the PID of TCC's conhost and then set a conhost-specific Win event hook to watch for the console being hidden or shown.
Code:
// This hook targets CONHOST and only receives SHOW/HIDE (0x8002, 0x8003) events.
VOID CALLBACK ShowHideMonitorProc(HWINEVENTHOOK hWinEventHook, DWORD event, HWND hwnd,
   LONG idObject, LONG idChild, DWORD dwEventThread, DWORD dwmsEventTime)
{
   if ( hwnd == global.hWndConsole )
   {
     // just to see it work
     Printf(L"%s\r\n", (event == EVENT_OBJECT_HIDE) ? L"HIDE" : L"SHOW");
   }
}

// After getting CONHOST's PID, this hook unhooks itself and sets
// a more appropriate one to watch for console hide or show.
VOID CALLBACK ConHostDiscoveryProc(HWINEVENTHOOK hWinEventHook, DWORD event, HWND hwnd,
   LONG idObject, LONG idChild, DWORD dwEventThread, DWORD dwmsEventTime)
{
   if ( hwnd == global.hWndConsole && global.dwConHostPid == 0 )
   {
     HANDLE hEventThread = OpenThread(THREAD_QUERY_LIMITED_INFORMATION, FALSE, dwEventThread);
     global.dwConHostPid = GetProcessIdOfThread(hEventThread);
     CloseHandle(hEventThread);
     UnhookWinEvent(hWinEventHook);
     SetWinEventHook(EVENT_OBJECT_SHOW, EVENT_OBJECT_HIDE, global.hThisModule,
       ShowHideMonitorProc, global.dwConHostPid, 0, WINEVENT_OUTOFCONTEXT);
   }
}

// in InitializePlugin()
  if ( global.hWndConsole != NULL ) // not for detached instances
   {
     // After getting the PID of CONHOST.EXE, this hook unhooks itself and sets another hook targeting
     // only CONHOST, the console window, and the events EVENT_OBJECT_SHOW and EVENT_OBJECT_HIDE.
     // Do this only in a thread that pumps messages.  Doing it here, in InitializePlugin(), works.
     SetWinEventHook(EVENT_MIN, EVENT_MAX, global.hThisModule, ConHostDiscoveryProc, 0, 0, WINEVENT_OUTOFCONTEXT);
   }
 
#13
P.S. ...

If you're not interested in getting conhost's PID, you can just set the show/hide WinEvent hook for all processes. That doesn't burden the system. I've been counting and in a couple hours of work, mine has gotten only a few hundred hits from other windows (when it returns immediately).
Code:
VOID CALLBACK ShowHideMonitorProc(HWINEVENTHOOK hWinEventHook, DWORD event, HWND hwnd,
   LONG idObject, LONG idChild, DWORD dwEventThread, DWORD dwmsEventTime)
{
   if ( hwnd == global.hWndConsole )
   {
     // just to see it work
     Printf(L"%s\r\n", (event == EVENT_OBJECT_HIDE) ? L"HIDE" : L"SHOW");
   }
}

  if ( global.hWndConsole != NULL ) // not for detached instances
   {
     SetWinEventHook(EVENT_OBJECT_SHOW, EVENT_OBJECT_HIDE, global.hThisModule,
                             ShowHideMonitorProc, 0, 0, WINEVENT_OUTOFCONTEXT);
   }