2

While "deploying" the solution from this question on a number of machines, I noticed some single core machines have terrible results (for example, the solution fails spectacularly on an intel atom).

What is happening here is the following. I call SetWinEventHook(...) to get callbacks for console changes. Due to the out-of-contex notification there is no synchronisation between the processing of the events and further changes on the console, so while multi core machines do well (not perfect btw), single core machines make a mess of this.

So I proceeded to turn on the In-Context notification since this should be synchronous according to the msdn. In c#, this is like asking for the Infinite Improbability Drive, so I created a simple dll in C that can do the dirty work, and talk to the dll from c#. So far so good.

As it turns out the callbacks happen in conhost.exe as opposed to the process owning the console. Now this presents a problem since in the callback I can't find a way to access the console output buffer in the context of conhost.exe. Or more precisely, I can't seem to find a way to obtain a handle to it. Here is what is avaliable: Handle to the console window, process id's of both the console application and conhost.exe and a pipe to the console application.

And here is what I tried sofar:

  1. using GetStdHandle(...), results in invalid handles (makes sense in the context of conhost.exe)
  2. using CreateFile("CONOUT$"...), dito
  3. using the pipe to have the console application read from the output buffer, results in deadlock. I suspect a locking mechanism for preventing reads while writing, that would make sense.
  4. duplicating the output buffer handle and passing it via the pipe. No joy because console handles cannot be duplicated to an external process.
  5. attaching the conhost.exe process to the console of the console process it is serving and then do the CreateFile thing. Ok this was my favorite one, but it also doesn't work since AttachConsole(...) blocks, similar to 3.

Someone have any ideas on what to try next? My c/c++/winapi skills are intermediate at best, so it is very possible I overlooked something. Ok an obvious one would be to throw the whole thing overboard and just poll the output buffer for changes, but I would consider that a last resort option. I'm assuming that MS was smart enough to make sure either In Context or Out of Context events would actually be usable and as such I must be missing something.

Community
  • 1
  • 1
Captain Coder
  • 798
  • 5
  • 12
  • What do you mean by 'fail spectacularly' - you never get events at all, or just very very late? One thing to be aware of with console events is that getting in-proc events from conhost is new in Win7; I think in Vista, the protected system process csrss.exe hosted the console, and since it's protected, you can't hook into it - so you'd still get out-of-proc events there, even if you ask for inproc. Random thought; if you're just getting events too late, one option might be to use the hook purely as a signal mechanism, eg. set event to wake/notify your main exe, and access console from there. – BrendanMcK Nov 28 '11 at 23:49
  • Also: what is it you are trying to do at this point? It sounds like you've detected the console has changed - you are now trying to read the new output? I don't think there's any way to read "from the other side" so that you can read what the other app just wrote. You can use the console APIs like ReadConsoleOutput() to extract the characters from the control 'screen', but that's not super useful for your scenario. On unix, the thing to do here would be to use a "pseudo tty", which is what ssh and the like actually use; though seems Win32 doesn't have a similar facility. – BrendanMcK Nov 29 '11 at 00:02
  • 1
    Indeed it gets events very late. It gets for example "coord x,y to z,a are updated" and a subsequent reading of those cooridnates then produces wrong results because the buffer might have scrolled before the event is processed, so the coordinates are misaligned. I have only windows 7 to deal with, but thanks for the pointer on backwards compat. The thought of using it as a signal also occured to me, it would save on the polling. I am indeed trying to use the console api (winevents in this case) to synchronously read changes on the console. – Captain Coder Nov 29 '11 at 06:51
  • 1
    Given that notifications are async, your best bet might be to keep track of the "last known console content" somewhere, and when you know a change has happened, fetch the new buffer, compare the two, and treat new output at the end as "the output stream". Hopefully you'll have enough lines in common between old and new to establish a context if the console does scroll - at least it only scrolls vertically! – BrendanMcK Nov 29 '11 at 10:03

0 Answers0