Welcome!

By registering with us, you'll be able to discuss, share and private message with other members of our community.

SignUp Now!

Loss of Focus After Operations (e.g., with XDIR)

No, build 37 doesn't work here either. Same results as above.

As I have already mentioned, I have never done any console programming (well except for numerous shell scripts). But... this smells like... two processes, threads, windows procedures etc. clashing. In my experience (which might well be orthogonal to the current problem) "forcing" one process to release control by posting a message to self often helped. Can you even do that in conhost/openconsole?
 
Here's something to try. It's a TCC plugin (fgtest.dll) that might solve the problem and/or shed more light on it. It uses a technique I used to use when TCC and WT didn't get along very well. In a nutshell, if the PseudoConsoleWindow gets foreground, it'll give foreground to TCMD. If it helps, I'll post the code (which is tiny) but I think Rex already knows the technique.
 

Attachments

No, build 37 doesn't work here either. Same results as above.

As I have already mentioned, I have never done any console programming (well except for numerous shell scripts). But... this smells like... two processes, threads, windows procedures etc. clashing. In my experience (which might well be orthogonal to the current problem) "forcing" one process to release control by posting a message to self often helped. Can you even do that in conhost/openconsole?

No, you can't send a message to a pseudoconsole. It doesn't have a window handle.
 
Trying one last build for tonight:


Let me know if the behavior is any different. Still unable to reproduce this here, on 5 systems, 3 Win 11 and 2 Win 10.

Microsoft is annoyingly vague about this topic; they say that depending on the Windows configuration an app may or may not be able to make another app the foreground. But they don't say what in the configuration determines this.
 
Yup! That's it. In both cases.

fgtest.dll did the trick, albeit being rather slow about it. But this might well be Windows Defender interfering. It didn't like the plugin being loaded.

The latest build of TCMD also works in all cases. And just to be clear about it: fgtest.dll was not loaded when testing.

Out of curiosity, what was the solution to the problem. You see: I might just learn something for the future. :-)
 
In build 38, all my use cases with focus issues (XDir, @GetDate, and command dialogs) are now working as expected,

Thanks for all the effort that went into figuring this out Rex!
 
Yup! That's it. In both cases.

fgtest.dll did the trick, albeit being rather slow about it. But this might well be Windows Defender interfering. It didn't like the plugin being loaded.

The latest build of TCMD also works in all cases. And just to be clear about it: fgtest.dll was not loaded when testing.

Out of curiosity, what was the solution to the problem. You see: I might just learn something for the future. :-)
What exactly did FGTEST.DLL do? This is what it's supposed to do:

If the PseudoConsoleWindow gets foreground, it will beep (to let you know it's working) and set the foreground window to TCMD and put the PseudoConsoleWindow at the bottom of the Z-order.

And that's all it does. If you didn't hear beeps, it did nothing. In my tests, dismissing XDIR never set the foreground window to the PseudoConsoleWindow, whereas dismissing the @GETDATE and @GETFILE dialogs and dismissing a command dialog (/=) did set the foreground window to the PseudoConsoleWindow.

If the latest TCC fixes everyone's problems that's good. I can't wait for others to comment.
 
@GETFILE[] exhibits undesired behavior (build 38); after it the FG window class is "PseudoConsoleWindow".

The FGTEST plugin fixes it. That plugin uses an undocumented API to get conhost's PID, then uses a process-specific (conhost), event-specific (EVENT_SYSTEM_FOREGROUND) WinEventHook to set things right. Here's most of the relevant code; the CPP file is attached.

Code:
VOID CALLBACK WinEventHookProc(HWINEVENTHOOK, DWORD, HWND hwnd, LONG, LONG, DWORD, DWORD)
{
    HWND hWndConsole = GetConsoleWindow();
    if ( hwnd != hWndConsole )
        return;
    Beep(440, 200); // so i know it was called
    SetForegroundWindow(hWndTCMD);
    SetWindowPos(hWndConsole, HWND_BOTTOM, 0, 0, 0, 0, SWP_HIDEWINDOW | SWP_NOMOVE | SWP_NOSIZE);
}

In InitializePlugin,

Code:
    const auto GetRealWindowOwner = (DWORD(WINAPI*)(HWND)) GetProcAddress(GetModuleHandleW(L"user32.dll"), MAKEINTRESOURCEA(2712));
    DWORD dwConHostPid = GetRealWindowOwner(GetConsoleWindow());
    hWinEventHook = SetWinEventHook(EVENT_SYSTEM_FOREGROUND, EVENT_SYSTEM_FOREGROUND, pluginfo.hModule, WinEventHookProc, dwConHostPid, 0, WINEVENT_OUTOFCONTEXT);
 

Attachments

GetConsoleWindow() returns 0 for ConPTY windows, so it's unclear to me how your SetWinEventHook will work.
I think that's (very) old behavior. I've been relying on it working for several years. I get this

Code:
0x410950 - PseudoConsoleWindow

from this

Code:
    HWND hWndConsole = GetConsoleWindow();
    WCHAR szClass[32];
    GetClassName(hWndConsole, szClass, 32);
    Printf(L"0x%I64X - %s\r\n", hWndConsole, szClass);
 
TCMD also.

1777318628705.webp
 
Doesn't work on my system; I always get 0 from GetConsoleWindow.
That's odd. Are you doing that in TCC and after the thorough establishment of the ConPty session?

I can't explain it. I don't think anything I did made it work.
 
I don't know what it means, but it works for me as well. This is in TCMD.

->echo %@winapi[kernel32,GetConsoleWindow]
396050

->echo %@winapi[user32,GetClassName,%@winapi[kernel32,GetConsoleWindow],buffer,32]
PseudoConsoleWindow

->ver
TCC 36.00.38 x64 Windows 11 [Version 10.0.26200.8246][/CODE]
TCC Build 38 Windows 11 Build 26200
Registered to DESKTOP-JAY
Build variable: 36.00.38
 
What exactly did FGTEST.DLL do?

Sorry if my last post was less than precise, but I was in a bit of a hurry to get out of the door on a visit to my sister. And that is precisely why I did not reply earlier, I got home only a few hours ago.

Here is what I did last Sunday with a little more detail.

1st test...
  • Copied the plugin into the installation folder of TCMD.
  • TCMD was still at build 37 (XDir OK, command dialogs not OK)
  • I did not bother to switch on the speakers (so no sound)
  • Loaded the plugin (Windows Defender balked, but I ignored it)
  • Started testing and noticed a pronounced delay between closing the dialogs and the prompt showing up (if I recall correctly the delay did not happen with XDir). The delay most probably must have been a beep, which I didn't hear and thus ascribed to Windows Defender interfering.
  • For each and every test the focus was back in TCMD afterwards.
  • So all an all the plugin did its work.
  • Next I unloaded the plugin and deleted its dll-file to minimize interference.

2nd test...
  • Installed the (then) latest build of TCMD (build 38)
  • Tested all dialogs (XDir, command dialogs, @Date, etc.)
  • Found that they where all working as expected, that is, in all cases the focus was back in TCMD after closing the dialogs

Finally...
  • posted a quick reply to the forum and left in a hurry.

I hope being unresponsive wasn't too annoying, but sometimes life interferes with "the real important things", like testing a new versions of a favorite software :-).
 
Last edited:
Doesn't work on my system; I always get 0 from GetConsoleWindow.

Build 38 (still installed after returning home; see post above)

[C:\]echo %@winapi[kernel32, GetConsoleWindow]
67784

[C:\]echo %@winapi[user32,GetClassName,%@winapi[kernel32,GetConsoleWindow],buffer,32]
PseudoConsoleWindow

After installing the latest build 39, I get the same results. Well, the handle is different, of course, but that is to be expected.
 
Thanks for that, @DieterKoessl. Defender doesn't complain here. The beep is 1/5 second long. Could that be the delay? In my experience dismissing XDIR apparently does not cause the GetConsoleWindow to become foreground so there would be no beep/delay. Again, in my experience, dismissing the XDIR /= dialog or %@GETDATE will be caught by the FGTEST plugin.
 
The beep is 1/5 second long.
Yes, that sounds about right (if memory serves well). The delay was noticeable and at the threshold of being annoying. The same thing which I would have done.

Does this suffice, or should I downgrade and verify the beep? Since TCMD doesn't like to be overwritten with an earlier version, I would have to uninstall and re-install.
 
FGTEST was only a test. There is no reason to continue using it. And I don't recommend messing with your installation.
 
Back
Top