Fun thought, that I never see anyone bring up. A Windows “window” is (and has been, since Windows 3.1) pretty much the same thing as an Erlang actor-process: a light pseudo-execution-thread that carries its own state and can send/receive arbitrary messages from peer windows, and—while normally only “doing” something when it receives a messsage— is conventionally driven to tick at regular intervals by timer messages it asks the system to schedule to send back to it.
It just-so-happens that unlike an actor-process, a Windows window usually has a GUI element attached to it. But not always! “Hidden windows”—i.e. plain actor-processes without the extra GUI bits—were the design pattern for doing background stuff for a long time before Windows introduced background services.
I bet some Windows developer here has a story of “that time I built an actor-modelled system just using Windows primitives.”
Alan Kay did actually say that he wished he'd built Smalltalk's GUI around a single class: "a smart rectangle that can contain other smart rectangles". In other words, Windows windows.
So like X11 windows when using the original drawing API, buttons and other elements are just a window inside a window that receive events when they have focus.
Yes. One of the reasons why Wine is a thing is because the primitives provided by X11 map nicely onto those provided by Windows. No Wayland port of Wine is in the immediate offing, also for this reason.
>“Hidden windows”—i.e. plain actor-processes without the extra GUI bits—were the design pattern for doing background stuff back then.
Isn't it still the same? cmd can't be hidden and this is the advice I found looking to do something around 5 years ago. Unless you want services but those have certain limitations. No idea why they found it appropriate to prevent services from interacting with the desktop post-XP.
It's a huge security risk. Background service typically runs at higher level of privilege. Letting it expose a UI element opens up a huge attack surface. Other much less privileged processes can send messages to its window. An old trick was to send SetWinEventHook message to a service's window to hook an event callback in a dll. The dll is run in the service window's process and thus with its privilege. Privilege elevation achieved!
They could simply check that only processes with the same privilege could communicate this way... not to mention the desktop user on Windows is usually the owner and has administrator privileges anyway.
Security context is not passed with Windows massage passing. Message passing is mainly for UI and requires all of the performance it can get. Checking access for every single message is too expensive. Just like TCP connection doesn't carry security context, you don't know what privilege the caller has.
Named pipe carries security context. That's why newer Windows requires background services to close off all outside contacts except named pipe, so the service can control the access level.
> No idea why they found it appropriate to prevent services from interacting with the desktop post-XP.
It’s an architecture thing. Background services are supposed to be light things that just do the stuff the user can’t do at their own privilege level; they aren’t supposed to do stuff at the user’s privilege level, like showing windows, because mixing in that secondary concern increases their attack surface. Instead, if you have some background system that has some user-level concerns (like a GUI) and some system-level concerns, you’re supposed to build it as two programs: a tray utility or configuration program, which acts as an IPC client; and a background service, which acts as an IPC server.
You’re correct in that, even today, if you want a background service to be able to just arbitrarily pop up a message to you, you’re going to be writing a tray utility as a Win32 process that starts with a rootmost hidden window, to catch the IPC message the background service sends.
I seem to remember Invoke and BeginInvoke in Windows Forms work by using SendMessage or PostMessage to send a reference to the delegate to the message queue. I vaguely remember apartment threading in COM does this as well.
> A quirk in the messaging system rears its head when you try to write a Windows-hosted debugger (also called a "GUI debugger"). A GUI debugger is a debugger for Windows programs that itself uses the Windows display mechanisms. What's the problem with that? Well, imagine the following scenario: A GUI debugger places a breakpoint inside of a Window procedure. Eventually, the debuggee program hits the breakpoint, and stops--and cannot call GetMessage() to yield control to other tasks! That means no other tasks--including the GUI debugger--can get their messages. The debugger can't even respond the mouse clicks that tell the debuggee to run again.
The effect still exists in some way in later version windows like the Windows Volume Mixer will freeze up or won't open if you have an application stopped at a breakpoint. I think it gets stuck waiting for a reply from something like WM_GETICON that it would have to send to top-level windows.
A single application blocked on a reply is very different from all applications halting because someone won't yield in a cooperative multitasking environment.
I would also say that anyone who sends a message to all top-level windows should use SendMessageCallback or similar so they can handle a reply asynchronously.
> Say your database program gets a WM_COMMAND message, which it interprets to mean, "Go sort this database of 300,000 records," and dutifully conducts this 45-minute operation;
Yep. Looks like somebody put in <a> tags with names around all the paragraphs to target them with links, then somebody else put in css to manually underline all a tags, not just ones with href's.
In Chrome just Right Click => Inspect one of the paragraphs, then in the element tree select one of the a tags and un-check the "#content .story a" css rule. Then your eyes will stop burning!
Ha, reminds me of the days I used WINAPI programming. The message pump would be done with a simple while loop that has GetMessage(), TranslateMessage() and DispatchMessage().
That knowledge is still valuable for example in figuring out why a WPF app doesn’t update its Ui. We have more abstractions today but under the hood it’s still the same.
I enjoyed this article very much. I still use SendMessage and heavily rely on pinvoke.net mainly for automating other programs. I have to take this opportunity to ask the crowd are there better resources or better tools for automation? Being retired, I mainly automate for my own amusement, websites and games on Bluestacks are my primary targets.
I've yet to see anything touted as groundbreaking on web front-ends that wasn't thoroughly explored by unix forty years ago or Windows twenty-five years ago.
react has a message passing system? maybe if you're talking about react + flux. also, in windows, there's no render() that declaratively renders your widgets.
It just-so-happens that unlike an actor-process, a Windows window usually has a GUI element attached to it. But not always! “Hidden windows”—i.e. plain actor-processes without the extra GUI bits—were the design pattern for doing background stuff for a long time before Windows introduced background services.
I bet some Windows developer here has a story of “that time I built an actor-modelled system just using Windows primitives.”