Not a lot of software really feels like "magic" to me anymore, which is unfortunate, but system programming on Windows often still feels like some arcane art.
The examples in the docs were also usually the bare minimum to show that the function existed, and usually full of memory leaks and bad behavior. Guessing what errors might arise was always fun. And then, the OS started inserting proxies on your interfaces whenever it wanted without telling you it might happen. Fun times all around.
Favorite “COM-ism”: IClassFactory, the basic interface to a class. Why not call it IClass? Or IFactory since a class is essentially a Factory pattern? IClassFactory makes it sound like a Factory for Classes, not objects.
Using COM from .net absolutely does not prevent leaks. I still don't really understand COM to this day, but I vividly recall spending significant effort and ultimately failing to do Office interop without leaking.
My experience using COM with .net is that the GC does not get the hint that there is significant memory that will be released when it drops the COM wrapper object, so a "big" COM object or even many ones will not make the runtime start a collection and it ends up as a leak even though kicking the GC would probably do the right thing.
So I would end up wrapping the objects in IDisposable and calling Marshal.ReleaseComObject on Dispose. Then COM objects were usually wrapped in using() to remain idiomatic for manual cleanup in c#.
If you put it in a C++ smart pointer it winds up pretty similar to ARC. (Yes, I have heard the compiler person's explanation that an ARC-type solution can generate fewer reference count modifications than a c++ smart pointer.)
I was a junior back then but COM felt like magic to me. I think MS made COM more arcane than necessary. It was not until I read the book Essential COM by Don Box that I understood COM.
"Essential COM" is one of the top computer books ever written and I'd recommend it to anyone who is interested in object systems even if they don't code for Windows. (e.g. I think better than "The Art of the MetaObject Protocol")
I have my copy from before the days when they tarted it up to add to the Developmentor series. I kinda miss Don Box doing his thing, quite an entertaining showman (who remembers Box sitting in a bath on stage talking about SOAP?) and tremendous technical writer.
The advice is still "don't use .NET managed code for your in-proc shell extension", but the given reasons are not necessarily specific to the .NET runtime:
1. The .NET framework CLR takes too long to load for an extension that could be loaded by any app that pops up shell UIs.
2. There are seams between .NET and COM even with interop. These seams open traps for you because the COM-era shell APIs (Windows 95 to Windows 7) were designed for people who write their shell extensions in C++ and so can deal with all the tricky details of COM.
Point 1 was temporarily obviated by .NET Native, but that has now been abandoned with no explicit replacement, leaving a hole only somewhat filled by a combination of Mono and CoreRT.
The explicit replacement was CoreRT. It's built in to the options of the dotnet CLI tool as of .NET 5, and supposed to get more complete as the Mono merger finishes early in .NET 6.
Actually if you look at the github issues and Build 2020 talks it still isn't quite clear how it goes.
Apparently they are more keen into going into a AOT + JIT mixed model, with the RoR (Ready to Run) images, specially if you take into consideration the talks done as guest at JVM Languages Summit 2019.
> We can cast it to an IWebBrowser (a remnant of when Internet Explorer and Windows Explorer were welded together)
Aargh. For a while I maintained an app which embedded IE (technically "IHTMLDocument2") on Windows CE, which meant dealing with a lot of this madness. It spawned all kinds of background threads and didn't take kindly to being interrupted, and control over it was limited - ended up drawing a window over its control bar and passing clicks through ourselves.
He mentions "the cultural defeat of Microsoft", which is absolutely right; developers no longer choose the Windows platform, they are only ever forced to by circumstance, and have developed tools like Electron which allow them to ignore the platform entirely.
For whatever reason, the "developer community" of Microsoft was very weak, at least post-dotcom era. You couldn't find many people talking about it openly to learn from. And only recently have they responded to that, especially with Roslyn and the buyout of Github.
I think a main reason Microsoft lost their development community is because they charged for access to Visual studio (which is the gateway to the entire ecosystem). People didn't talk about it openly, because no one was building for the microsoft platform outside of work.
Meanwhile a whole community of competing free alternatives appeared - students learnt Java and Python because C# was a paid product that was also not cross platform.
That free license was called Express, was available per language variant, so you needed on VS Express install per workload and exists since around 2005, until Community made its appearance.
Also the Windows SDK was always available for free, just you needed to get a C compiler yourself.
> Also the Windows SDK was always available for free, just you needed to get a C compiler yourself.
Not quite _always_... For the first few versions of Windows, the SDK was a fairly expensive separate product you had to buy in addition to the compilers itself. I'm pretty sure it was MS C/C++ 7 that was first available bundled with the SDK. IIRC, the product was $700-800 (in 1990 money), took a couple feet of shelf space, and shipped with seven or eight thousand pages of documentation.
Visual C++ (really MS C/C++ _8_) democratized it a bunch by shipping with the libraries/tools needed to develop for Windows and offering a basic product at a <$200 price point. That was also the first version of Microsoft C that shipped with a Windows-based debugging UI.
The early 90's also saw the introduction of MSDN - the Microsoft Developer Network. At the time, this was a subscription CD based library of essentially all of Microsoft's developer documentation (as well as a few tools, etc.) It was essential... and to put the timeline in perspective, Microsoft sold a version of MSDN that was bundled with a CD-ROM drive, since they were as uncommon as they were at the time. They quickly added a premium version of MSDN that got you the full tooling also.
Ten or fifteen years after all that, the full version of Visual Studio was a $10k/seat proposition. Between that and all of the API churn, they lost sight of their original goal of staying developer friendly, and it was to their deteriment. (Particularly given the concurrent ascendence of the Web, OS X, Mobile, Linux, and the like.)
I started developing for Windows 3.0 using Borland tools and never paid more than 100 euro (when converted for today's money) with their Turbo C++ and Pascal compilers, the Windows SDK was in the box.
Have been developing for Windows and UNIX flavors ever since.
Windows has been always developer friendly from my point of view, more so than UNIX ever was, then again I guess we have different points of view what being developer friendly actually means.
> I started developing for Windows 3.0 using Borland tools and never paid more than 100 euro (when converted for today's money) with their Turbo C++ and Pascal compilers, ...
> I guess we have different points of view what being developer friendly actually means.
We may be in more agreement than you suspect, for what it's worth - I think it's mainly a matter of timing. The development community, including Borland, pivoted from OS/2 to Windows right around the 1990 release of 3.0. That forced Microsoft to open up a lot of the tooling required to compile Windows binaries. (IIRC, the effort was something like Open Tools, and there was also ToolHelp, which was Microsoft's way of opening up Win16 debugger support that had been previously proprietary.) This was a big part of the reason that companies like Borland could ship products that let you code for Windows without an SDK.
Prior to that point... 1985-1989/90, the situation was a lot more closed and tools like the SDK were extra cost add ons.
Borland just made one attempt at OS/2, and it wasn't as good as Visual Age for C++ and CSet++. There was hardly anything to pivot from.
As for Windows 1.0 - 2.0, which is the time frame you are talking about, Windows did not matter at all. We only cared about MS-DOS and compatibles.
And on MS-DOS, their Pascal and C offerings were quite lousy when compared with the competition, so we were gladly giving money to TMT, Borland, Nanuteck, Gardens Point, Watcom.
They were also ironically the last C compiler vendor for MS-DOS to add support for C++, the very last edition of their compiler for MS-DOS, Microsoft C/C++ v7.
And in what concerns freely available, MS-DOS did not had any SDK, so yeah we had to pay for a book with the BIOS and Int 21h documentation, like PC Systems Internals.
Back in the 90's I used to be the custodian and curator of our great big box of MSDN CD's ensuring that updates and replacements were properly seen to. Oh the memories :)
In fairness you didn't just get the development tools, you also got copies of just about every MS server and office product on what were fairly generous developer licenses. Many of these things didn't even require phoning home for "activation" and MS turned a blind eye to partners sharing one copy amongst 10-15 devs; after all the real money was where the fruit of our efforts would be deployed, stuff running in banks and other corporates paying serious coin for server licenses and direct support. Ultimately all this stuff was about capturing developers mindsets with a view to selling production licenses.
> In fairness you didn't just get the development tools, you also got copies of just about every MS server and office product on what were fairly generous developer licenses.
It didn't start out that way... they added a premium level later, and that was the version that included all the free tooling. I still have volumes 3 and 5 (April 1993 and Fall 1993), and it's a single CD product that was mostly focused on just the documentation. (This is actually how I got my first CD-ROM drive... IIRC, the whole package, a one year subscription and a proprietary interface CD-ROM was $400).
I really don't understand Microsoft's pricing model for Visual Studio.
In theory, it's just price discrimination; put features that are only valuable to enterprise customers in the $6k/year version, and profit. But then they put key UX features which are useful to _everyone_, like Live Unit Testing, in the Enterprise version too.
The upshot is that they sell a few more Enterprise licenses, but the development experience is worse for 99% of .NET developers on Windows. It's such a weird contrast to their developer tooling strategy in every other area.
When I was a poor Comp Sci student I couldn't afford Visual Studio so I got an IRC buddy to mail me a pirated copy of Visual Studio Enterprise Edition (gotta love rural dial-up internet.) This was around 2003 I believe.
Package never arrived, so I got him to re-send it. Got the discs a few weeks later.
Some time later I got a call from the RCMP -- Canadian version of the FBI. They wanted me to come to their detachment and answer some questions. When I showed up they took me into an interrogation room and told me they had seized the CD-Rs at the border, that software piracy was a big deal and he had been instructed by his superiors to "make an example out of someone."
They wanted to know who sent them, how I got in contact with him, how much I had paid him, and a lot of other questions. I was 19 and scared shitless. I had seen the warnings at the beginning of Hollywood movies, I should have asked for a lawyer but didn't.
I gave a statement and signed it. I told them that the guy had re-sent the discs and I received them, what should I do? They told me to bring the discs in, and I did.
Never heard from them again. No criminal record. I have no idea what happened behind the scenes, but I thank my lucky stars that I wasn't charged with copyright infringement.
I'm not trying to paint this as some kind of Les Miserables bread-loaf-stealing tragedy, but I am beyond ecstatic at the wealth of free software development tools available to anyone with a $400 laptop.
I was thinking along the same lines. WSL looks like a half-hearted and late attempt to put some POSIX lipstick on the Windows pig, but for me at least it doesn't really stick. The implementation is as messy and intransparent as usual in Windows. When I have to use Windows, Cygwin is still my tool of choice to make the system usable at all.
I see it as a transition layer. Apple can get away with "sorry we've just changed architecture, all your binaries are obsolete again, deal with it" but Windows can't. The ground is being laid, piece by tiny piece, for more POSIXism. The two most visible warts - CRLF and '\' - are the ones to watch for when they get deprecated.
> The two most visible warts - CRLF and '\' - are the ones to watch for when they get deprecated.
There's a third wart, the path length limit of 260 characters. Work on that seems to already be in progress: https://docs.microsoft.com/pt-br/archive/blogs/jeremykuhne/n... (though I see no mention of a related and more annoying wart, which is not allowing some simple file names like "aux.c").
> Don't expect AUX, COM1, etc to be fixed any time soon, because that is a huge backwards compatibility issue.
I think that this is also possible to fix. Always require the colon ('CON:' instead of 'CON'), and make this opt-in per process, like "longPathAware".
Sure, old apps will choke if you now create a CON file. But 1) the file dialogs could show a warning when doing that, 2) you can already create filenames that make old apps choke and 3) they could transparently show them as CON~1 or something in those old apps.
A warning wouldn't really fix much for most people. »This file name might potentially not work in certain applications« is far too vague for anyone to determine whether it's a good idea to name the file that way or not. And erring on the side of caution brings you to the same situation as right now that you better avoid those names. For the dedicated there's a way to create them anyway, and many power user tools allow you to create and handle them.
Every Windows shell (CMD.EXE and PowerShell and even File Explorer) has always accepted / paths. \ paths will never go away due to backwards compatibility. Most Windows apps happily work with documents that are CR only, including Notepad since Windows 7 IIRC. CRLF will likely stay the default for backward compatibility reasons, too. You can blame IBM for both of those things as IBM mainframes were CRLF and IBM thought / a better option prefix key than a path separator.
Note that paths with / won't always work in cmd when using built-in commands. For executables and their command lines, sure, but for at least some built-in commands you must use \ for path arguments because the parser otherwise parses an option.
Not sure about CR-only, but Notepad only recently-ish (a year ago, perhaps) gained the ability to work with LF-only text files. Mind you, that's probably not a fix in Notepad, but really in the decades-old Win32 edit control ... (which might give a hint as to why this was neither much of a priority, nor probably an easy fix while not breaking anything else).
Right, I meant LF-only, that was a brain fart. It is recent to Notepad, but I don't it is that recent. But yes, also Notepad for a long time was the simplest wrapper around the Win32 edit control possible, and likely rarely a priority. (Similar too how long WordPad was merely the simplest wrapper around the RTF control.)
20 years ago I knew COM inside out and it was great, it was really powerful way to integrate your own code with the big applications Excel, ASP, IE. Its a great way to do SOLID programming long before it became fashionable. It also did things like let you build components in a single threaded language and use from a multi thread process - stuff people still can't do today.
I know MS technology was never popular in SV, but people never even looked at it, which to me is weird when developers spend a lot of time investigating other languages and frameworks.
Anyway its mostly dead now I guess, except for these random archaeological digs.
DCOM was a couple of orders of magnitude more fiddly to get working. But amazing once it worked. Create an object on another server, call its methods, side effects happen on that server, results are returned to your process.
When I was learning Go the similarity between COM interfaces and Go interfaces really helped me grok them quicker.
DCOM was also amazing, in how much surface area it exposed to the network. Random COM objects which were never intended to be called remotely, and were poorly secured, could be exposed by accident.
So in the infamous Windows XP SP2 (not a major release of the operating system, but a mere service pack), DCOM got locked down hard. If you have a legitimate use for DCOM (like an OPC-DA server), you have to toggle several obscure settings to make it work again (see https://www-bd.fnal.gov/controls/opc/Using_OPC_via_DCOM_with... for a fourteen-page tutorial).
I like to compare HTTP / REST / HATEOAS with DCOM, conceptually.
DCOM was deeply misguided as a model for distributed programming. When you look at an actually functioning system, you realize that network transparency at the programming level is possibly the worst thing you can do. Can you imagine how web pages would work under a DCOM model?
COM is quite alive, after Longhorn's project failure, all those .NET ideas got re-implemented as COM and all major Windows APIs since Vista have been introduced as COM based APIs.
WinRT/UWP is just COM improved to support generics and .NET types.
It is pretty much alive despite not being popular in SV, and it is also how iDevices drivers work actually.
I know where you're coming from, given Longhorn's original history as an effort to implement part of Windows on .Net, but it's still interesting to see it cast this way.
Without getting too deep into the gory details, COM was originally the implementation technology for OLE 2.0, with the CLR being a combination of efforts to replace COM and compete with Java/JVM. (At least partially in response to the Sun lawsuit over Microsoft's attempts to extend Java directly.)
Sure it is interesting to see it this way, WinRT is what COM would have been if it wasn't the idea to turn around and make use of Java instead (via J++), see the Ext-VOS project and the history of F# for the juicy details.
Hence why many .NET configuration flags still have COM prefix to this day.
Also check the C++/COM Hilo project released for Vista, and updated for Windows 7 release
And I like how you only have to know the library/class/interface guid. No header files, nothing to link, the compiler figures out and infers everything. Type libraries make it possible to use the same component in a language-independent manner; bindings are generated automatically from TLB data.
> Anyway its mostly dead now I guess, except for these random archaeological digs.
Far from dead. All new windows stuff is built on top of extended COM.
You still definitely need to know COM to write Windows apps. I had to learn a lot of COM in the last five years. Granted, the Windows desktop isn't exactly a growth market nowadays. (Note that all the apps I've worked on are cross-platform and aren't Windows-specific, so COM use is limited to implementations of the platform abstraction layer.)
This takes me back! I was a COM expert in the late 90's/early aughts. It was important technology to master for building desktop applications for Windows.
Nowadays we don't typically build desktop applications and even when we do we typically employ cross-platform technologies. So COM has pretty much fallen by the wayside - which isn't a bad thing! We've moved on.
The idea of an app being a graph of polyglot components lives on, however, in the guise of microservices. The good part is you know everything exists out of process and you don't have to worry about things like COM's threading apartment. The bad thing is, of course, everything is out of process.
A common pattern for COM projects, in my experience, was a VB front end talking to a C++ back end. This was usually a pretty brutal experience TBH, even with ATL, because there were many fiddly details that intruded, specifically:
- reference counting
- string incompatibilities, exacerbated by the tendency of every man and his dog at Microsoft with an internet audience writing their own COM string class for C++ and publishing it; IIRC BSTR, _bstr_t, CCOMBStr but there were surely others, none of which really succeeded in bridging the very large gap that exists between what COM things a string should look like (length encoded at the front, two bytes per char) and the C / C++ view.
I'm currently working on a VB6 front-end (I say front end, but it 450,000 lines so probably a bit more to it!) with C++ back-end (and it's old C++ that uses MFC containers instead of std). We also have a lot of C# extras that are called from the VB6 and also consume the C++ stuff.
Oh, and there is Python scripting in there somewhere too.
I remember stumbling over shell and namespace extensions (without knowing the names of those concepts) back when I was coding in VB in high school - and being impressed how deep programs were apparently able to integrate into "the OS". (Nevermind that it was just the shell).
So it's really amazing to see giving step-by-step examples of how a namespace extension could be implemented.
I remember in particular that MS Outlook implemented their desktop icon as a namespace extension instead of an ordinary shortcut. I never understand why it was done this way, as the icon didn't behave particularly different than a normal shortcut: The only practical differences were that it did not allow you to look up the exe path and that you could not remove it from the desktop short of uninstalling Outlook.
I wonder if this was done purely for nerd cred in much the same manner as the author of the OP - or if some overzealous manager had an irrational fear of users deleting the "Outlook" icon and ordered their team to do anything in their power prevent that...
> and being impressed how deep programs were apparently able to integrate into "the OS". (Nevermind that it was just the shell).
I’ve always been annoyed that all the major OSes have all this GUI-shell-level virtual folders and namespaces stuff, but none of them bother to “push it down” such that it’s accessible by the command-line, or better, by syscalls.
I feel it would have made a lot of sense to do this in Windows: just replace “shell” objects with NT kernel objects, and allow the writing of (userland) NT-kernel-object-namespace extensions. Like FUSE, but without the filesystem part.
The whole point is the decoupling of userland from the kernel. Windows doesn’t really have syscalls in the Linux sense, but has an even more stable interface in the various core dlls (kernel32, user32, shell32, etc) (and of course the Nt* “syscalls” for speaking with the kernel directly).
COM was always the real api for interacting with the desktop environment/shell, even from cli applications. The problem is that COM is strictly object oriented (unlike the user32 api and co) but both C and C++ used the same bindings to interface with it, which were written at the lowest common denominator giving us C++ com wrappers were ugly as hell when they could have been so much nicer. Microsoft finally fixed that in the past couple of years with the new winrt api for C++ but the world would have been different if such COM bindings for C++ had existed twenty years ago.
> The whole point is the decoupling of userland from the kernel.
Decoupling is good; but this isn't just decoupling, it's encapsulation. The problem with graphical "shells" / userland object systems is that they treat the OS kernel as something to run on top of — to abstract away and mostly ignore — rather than something to implement themselves in terms of. The shell isn't described to the kernel in a way where shell objects are in any way "visible" or "accessible" to the kernel. Instead, in the major OSes, shell state (shell objects, namespaces, etc.) lives only in the shell; as far as the kernel is concerned, it doesn't exist.
Now, I have no opinion on whether shell state should actually "live" in the shell, vs. in the kernel (or in kernel-accessible subsystems, if we're talking microkernels.) It's probably better engineering-wise to keep shell-level state in userland.
But the kernel should still be able to interact with that userland shell state. The shell should be built such that it's easy for the kernel to enumerate and manipulate its objects. And the kernel should be built to know about the stable abstractions that make up the shell object runtime.
Where we are today, with shells opaque to kernel understanding:
• The Windows CLI sees my Windows network shares, and mounted drives from disk extensions, but not my Windows shell namespaces, nor my volume-ID-only mounts
• The macOS Finder can treat bundles as files (for e.g. copy/move operations, atomic backup, last-accessed versioning, etc.), but the BSD CLI just sees .bundle directories and needs special help to emulate the Finder approach
• Windows and macOS both treat directories containing only file-reified shell-level metadata (Desktop.ini/Thumbs.db, .DS_Store, AppleDouble files) as "empty" for purposes of preview / overwrite / merge / safe deletion – but their CLIs don't
• Both Windows and GNOME allow me to browse within compressed files, but only when going through the shell, not through the CLI, and not even when going through older APIs like Win16
• The Linux binfmt_misc driver needs shebang lines, despite the existence of file extensions, MIME-type xattrs, and shell file-association preferences tables
• Files marked as "quarantined" in macOS just look like regular files in the CLI, and no CLI program chokes on them, allowing scripted operations against such files to get quite deep in, until they hit some Cocoa-enabled subtask like codesign(8) that suddenly chokes on the quarantined input
I'm not totally sure on what a good solution to all this would look like, but I imagine it'd look like a replacement of all the custom kernel-to-userland callback APIs with a sort of "kernel-supported COM" where the kernel can talk to userland processes as if it were just another userland process making a COM request; and then the kernel can end up holding onto userland process COM object proxy-handles, passing them around, putting them into other kernel structs, etc.
Ideally, I think, the kernel would be responsible for declaring the contracts/interfaces that all shells running on that OS must implement themselves in terms of. Then "shell objects" would just be pure-userland kernel objects (i.e. defined by kernel base-classes, but with no kernel code in their codepath at runtime), sort of like Linux vDSOs are pure-userland kernel drivers.
Linux isn't really "ready" for this change—there are some gnarly legacy kernel-structs that need to retain their shapes and semantics, due to them being directly userland-visible without an intermediate view layer. But WinNt could totally do this, implemented almost entirely in terms of opaque kernel-object handles as it is. Nt-level structs don't matter one whit to userland, so they're free to be changed to retain opaque shel...
They exist, when you use alternatives like C++ Builder.
C++/CX was the closer that they got to it, and it remains to be seen how much complains are they willing to keep taking until C++/WinRT matches C++/CX tooling.
And I fully agree with you, C++ Builder and also Delphi have proven that such bindings were already possible 20 years ago, but for whatever reason there are some key devs (or management) at Microsoft that keeps pushing back for such productivity and brings out stuff like ATL/WRL instead.
I like COM/UWP, but boy some of the decisions just don't make sense.
> The real sad part is for things like this, because the documentation is so lacking/missing, is that you may run into issues where not even Stack Overflow can help you.
This is how we used to write code, back in the day. If you had a particularly hard time and experimentation wasn't working well, you traced through the disassembly in the debugger.
A good while back Esri rearchitected their whole software suite into a COM based technology known as ArcObjects, with the aim of providing developers a single environment in which to code across all Esri SDKs. I remember a couple of things about it: firstly it was reputedly the largest COM library in existence, and secondly it was so horrendous that hardly anyone used it.
Don't even get me started on the Java wrappers for ArcObjects... Thank god things have moved on.
66 comments
[ 2.3 ms ] story [ 146 ms ] threadFavorite “COM-ism”: IClassFactory, the basic interface to a class. Why not call it IClass? Or IFactory since a class is essentially a Factory pattern? IClassFactory makes it sound like a Factory for Classes, not objects.
With an interface like AddRef/Release, they all but guarantee memory leaks.
Developers that know what they are doing would use a C++ library with support for COM smart pointers, .NET or Delphi.
So I would end up wrapping the objects in IDisposable and calling Marshal.ReleaseComObject on Dispose. Then COM objects were usually wrapped in using() to remain idiomatic for manual cleanup in c#.
That was some years ago.
https://github.com/dwmkerr/sharpshell/issues/197
Has that changed by now?
[0] https://devblogs.microsoft.com/oldnewthing/20061218-01/?p=28...
https://docs.microsoft.com/en-us/archive/msdn-magazine/2009/...
Also note that Windows development team doesn't have that much .NET love (owned by DevTools).
The advice is still "don't use .NET managed code for your in-proc shell extension", but the given reasons are not necessarily specific to the .NET runtime:
1. The .NET framework CLR takes too long to load for an extension that could be loaded by any app that pops up shell UIs.
2. There are seams between .NET and COM even with interop. These seams open traps for you because the COM-era shell APIs (Windows 95 to Windows 7) were designed for people who write their shell extensions in C++ and so can deal with all the tricky details of COM.
Apparently they are more keen into going into a AOT + JIT mixed model, with the RoR (Ready to Run) images, specially if you take into consideration the talks done as guest at JVM Languages Summit 2019.
Aargh. For a while I maintained an app which embedded IE (technically "IHTMLDocument2") on Windows CE, which meant dealing with a lot of this madness. It spawned all kinds of background threads and didn't take kindly to being interrupted, and control over it was limited - ended up drawing a window over its control bar and passing clicks through ourselves.
He mentions "the cultural defeat of Microsoft", which is absolutely right; developers no longer choose the Windows platform, they are only ever forced to by circumstance, and have developed tools like Electron which allow them to ignore the platform entirely.
For whatever reason, the "developer community" of Microsoft was very weak, at least post-dotcom era. You couldn't find many people talking about it openly to learn from. And only recently have they responded to that, especially with Roslyn and the buyout of Github.
https://www.devever.net/~hl/windowsdefeat
Meanwhile a whole community of competing free alternatives appeared - students learnt Java and Python because C# was a paid product that was also not cross platform.
With .Net core you can get by with never touching VS. But that wasn’t always the case.
I also don’t believe MS had a free livense of Visual Studio like they do now.
Also the Windows SDK was always available for free, just you needed to get a C compiler yourself.
Not quite _always_... For the first few versions of Windows, the SDK was a fairly expensive separate product you had to buy in addition to the compilers itself. I'm pretty sure it was MS C/C++ 7 that was first available bundled with the SDK. IIRC, the product was $700-800 (in 1990 money), took a couple feet of shelf space, and shipped with seven or eight thousand pages of documentation.
Visual C++ (really MS C/C++ _8_) democratized it a bunch by shipping with the libraries/tools needed to develop for Windows and offering a basic product at a <$200 price point. That was also the first version of Microsoft C that shipped with a Windows-based debugging UI.
The early 90's also saw the introduction of MSDN - the Microsoft Developer Network. At the time, this was a subscription CD based library of essentially all of Microsoft's developer documentation (as well as a few tools, etc.) It was essential... and to put the timeline in perspective, Microsoft sold a version of MSDN that was bundled with a CD-ROM drive, since they were as uncommon as they were at the time. They quickly added a premium version of MSDN that got you the full tooling also.
Ten or fifteen years after all that, the full version of Visual Studio was a $10k/seat proposition. Between that and all of the API churn, they lost sight of their original goal of staying developer friendly, and it was to their deteriment. (Particularly given the concurrent ascendence of the Web, OS X, Mobile, Linux, and the like.)
Have been developing for Windows and UNIX flavors ever since.
Windows has been always developer friendly from my point of view, more so than UNIX ever was, then again I guess we have different points of view what being developer friendly actually means.
> I guess we have different points of view what being developer friendly actually means.
We may be in more agreement than you suspect, for what it's worth - I think it's mainly a matter of timing. The development community, including Borland, pivoted from OS/2 to Windows right around the 1990 release of 3.0. That forced Microsoft to open up a lot of the tooling required to compile Windows binaries. (IIRC, the effort was something like Open Tools, and there was also ToolHelp, which was Microsoft's way of opening up Win16 debugger support that had been previously proprietary.) This was a big part of the reason that companies like Borland could ship products that let you code for Windows without an SDK.
Prior to that point... 1985-1989/90, the situation was a lot more closed and tools like the SDK were extra cost add ons.
As for Windows 1.0 - 2.0, which is the time frame you are talking about, Windows did not matter at all. We only cared about MS-DOS and compatibles.
And on MS-DOS, their Pascal and C offerings were quite lousy when compared with the competition, so we were gladly giving money to TMT, Borland, Nanuteck, Gardens Point, Watcom.
They were also ironically the last C compiler vendor for MS-DOS to add support for C++, the very last edition of their compiler for MS-DOS, Microsoft C/C++ v7.
And in what concerns freely available, MS-DOS did not had any SDK, so yeah we had to pay for a book with the BIOS and Int 21h documentation, like PC Systems Internals.
Back in the 90's I used to be the custodian and curator of our great big box of MSDN CD's ensuring that updates and replacements were properly seen to. Oh the memories :)
In fairness you didn't just get the development tools, you also got copies of just about every MS server and office product on what were fairly generous developer licenses. Many of these things didn't even require phoning home for "activation" and MS turned a blind eye to partners sharing one copy amongst 10-15 devs; after all the real money was where the fruit of our efforts would be deployed, stuff running in banks and other corporates paying serious coin for server licenses and direct support. Ultimately all this stuff was about capturing developers mindsets with a view to selling production licenses.
It didn't start out that way... they added a premium level later, and that was the version that included all the free tooling. I still have volumes 3 and 5 (April 1993 and Fall 1993), and it's a single CD product that was mostly focused on just the documentation. (This is actually how I got my first CD-ROM drive... IIRC, the whole package, a one year subscription and a proprietary interface CD-ROM was $400).
Doubly so if you are a newcomer to programming.
In theory, it's just price discrimination; put features that are only valuable to enterprise customers in the $6k/year version, and profit. But then they put key UX features which are useful to _everyone_, like Live Unit Testing, in the Enterprise version too.
The upshot is that they sell a few more Enterprise licenses, but the development experience is worse for 99% of .NET developers on Windows. It's such a weird contrast to their developer tooling strategy in every other area.
Package never arrived, so I got him to re-send it. Got the discs a few weeks later.
Some time later I got a call from the RCMP -- Canadian version of the FBI. They wanted me to come to their detachment and answer some questions. When I showed up they took me into an interrogation room and told me they had seized the CD-Rs at the border, that software piracy was a big deal and he had been instructed by his superiors to "make an example out of someone."
They wanted to know who sent them, how I got in contact with him, how much I had paid him, and a lot of other questions. I was 19 and scared shitless. I had seen the warnings at the beginning of Hollywood movies, I should have asked for a lawyer but didn't.
I gave a statement and signed it. I told them that the guy had re-sent the discs and I received them, what should I do? They told me to bring the discs in, and I did.
Never heard from them again. No criminal record. I have no idea what happened behind the scenes, but I thank my lucky stars that I wasn't charged with copyright infringement.
I'm not trying to paint this as some kind of Les Miserables bread-loaf-stealing tragedy, but I am beyond ecstatic at the wealth of free software development tools available to anyone with a $400 laptop.
Most countries have Microsoft sponsored education programs and all big software shops have MSDN subscriptions anyway.
I was thinking along the same lines. WSL looks like a half-hearted and late attempt to put some POSIX lipstick on the Windows pig, but for me at least it doesn't really stick. The implementation is as messy and intransparent as usual in Windows. When I have to use Windows, Cygwin is still my tool of choice to make the system usable at all.
There's a third wart, the path length limit of 260 characters. Work on that seems to already be in progress: https://docs.microsoft.com/pt-br/archive/blogs/jeremykuhne/n... (though I see no mention of a related and more annoying wart, which is not allowing some simple file names like "aux.c").
Don't expect AUX, COM1, etc to be fixed any time soon, because that is a huge backwards compatibility issue.
I think that this is also possible to fix. Always require the colon ('CON:' instead of 'CON'), and make this opt-in per process, like "longPathAware".
Sure, old apps will choke if you now create a CON file. But 1) the file dialogs could show a warning when doing that, 2) you can already create filenames that make old apps choke and 3) they could transparently show them as CON~1 or something in those old apps.
Not sure about CR-only, but Notepad only recently-ish (a year ago, perhaps) gained the ability to work with LF-only text files. Mind you, that's probably not a fix in Notepad, but really in the decades-old Win32 edit control ... (which might give a hint as to why this was neither much of a priority, nor probably an easy fix while not breaking anything else).
I know MS technology was never popular in SV, but people never even looked at it, which to me is weird when developers spend a lot of time investigating other languages and frameworks.
Anyway its mostly dead now I guess, except for these random archaeological digs.
DCOM was a couple of orders of magnitude more fiddly to get working. But amazing once it worked. Create an object on another server, call its methods, side effects happen on that server, results are returned to your process.
When I was learning Go the similarity between COM interfaces and Go interfaces really helped me grok them quicker.
So in the infamous Windows XP SP2 (not a major release of the operating system, but a mere service pack), DCOM got locked down hard. If you have a legitimate use for DCOM (like an OPC-DA server), you have to toggle several obscure settings to make it work again (see https://www-bd.fnal.gov/controls/opc/Using_OPC_via_DCOM_with... for a fourteen-page tutorial).
DCOM was deeply misguided as a model for distributed programming. When you look at an actually functioning system, you realize that network transparency at the programming level is possibly the worst thing you can do. Can you imagine how web pages would work under a DCOM model?
WinRT/UWP is just COM improved to support generics and .NET types.
It is pretty much alive despite not being popular in SV, and it is also how iDevices drivers work actually.
I know where you're coming from, given Longhorn's original history as an effort to implement part of Windows on .Net, but it's still interesting to see it cast this way.
Without getting too deep into the gory details, COM was originally the implementation technology for OLE 2.0, with the CLR being a combination of efforts to replace COM and compete with Java/JVM. (At least partially in response to the Sun lawsuit over Microsoft's attempts to extend Java directly.)
Hence why many .NET configuration flags still have COM prefix to this day.
Also check the C++/COM Hilo project released for Vista, and updated for Windows 7 release
> Anyway its mostly dead now I guess, except for these random archaeological digs.
Far from dead. All new windows stuff is built on top of extended COM.
Nowadays we don't typically build desktop applications and even when we do we typically employ cross-platform technologies. So COM has pretty much fallen by the wayside - which isn't a bad thing! We've moved on.
Everything old is new again.
- reference counting
- string incompatibilities, exacerbated by the tendency of every man and his dog at Microsoft with an internet audience writing their own COM string class for C++ and publishing it; IIRC BSTR, _bstr_t, CCOMBStr but there were surely others, none of which really succeeded in bridging the very large gap that exists between what COM things a string should look like (length encoded at the front, two bytes per char) and the C / C++ view.
Oh, and there is Python scripting in there somewhere too.
Ungh.
So it's really amazing to see giving step-by-step examples of how a namespace extension could be implemented.
I remember in particular that MS Outlook implemented their desktop icon as a namespace extension instead of an ordinary shortcut. I never understand why it was done this way, as the icon didn't behave particularly different than a normal shortcut: The only practical differences were that it did not allow you to look up the exe path and that you could not remove it from the desktop short of uninstalling Outlook.
I wonder if this was done purely for nerd cred in much the same manner as the author of the OP - or if some overzealous manager had an irrational fear of users deleting the "Outlook" icon and ordered their team to do anything in their power prevent that...
I’ve always been annoyed that all the major OSes have all this GUI-shell-level virtual folders and namespaces stuff, but none of them bother to “push it down” such that it’s accessible by the command-line, or better, by syscalls.
I feel it would have made a lot of sense to do this in Windows: just replace “shell” objects with NT kernel objects, and allow the writing of (userland) NT-kernel-object-namespace extensions. Like FUSE, but without the filesystem part.
COM was always the real api for interacting with the desktop environment/shell, even from cli applications. The problem is that COM is strictly object oriented (unlike the user32 api and co) but both C and C++ used the same bindings to interface with it, which were written at the lowest common denominator giving us C++ com wrappers were ugly as hell when they could have been so much nicer. Microsoft finally fixed that in the past couple of years with the new winrt api for C++ but the world would have been different if such COM bindings for C++ had existed twenty years ago.
Decoupling is good; but this isn't just decoupling, it's encapsulation. The problem with graphical "shells" / userland object systems is that they treat the OS kernel as something to run on top of — to abstract away and mostly ignore — rather than something to implement themselves in terms of. The shell isn't described to the kernel in a way where shell objects are in any way "visible" or "accessible" to the kernel. Instead, in the major OSes, shell state (shell objects, namespaces, etc.) lives only in the shell; as far as the kernel is concerned, it doesn't exist.
Now, I have no opinion on whether shell state should actually "live" in the shell, vs. in the kernel (or in kernel-accessible subsystems, if we're talking microkernels.) It's probably better engineering-wise to keep shell-level state in userland.
But the kernel should still be able to interact with that userland shell state. The shell should be built such that it's easy for the kernel to enumerate and manipulate its objects. And the kernel should be built to know about the stable abstractions that make up the shell object runtime.
Where we are today, with shells opaque to kernel understanding:
• The Windows CLI sees my Windows network shares, and mounted drives from disk extensions, but not my Windows shell namespaces, nor my volume-ID-only mounts
• The macOS Finder can treat bundles as files (for e.g. copy/move operations, atomic backup, last-accessed versioning, etc.), but the BSD CLI just sees .bundle directories and needs special help to emulate the Finder approach
• Windows and macOS both treat directories containing only file-reified shell-level metadata (Desktop.ini/Thumbs.db, .DS_Store, AppleDouble files) as "empty" for purposes of preview / overwrite / merge / safe deletion – but their CLIs don't
• Both Windows and GNOME allow me to browse within compressed files, but only when going through the shell, not through the CLI, and not even when going through older APIs like Win16
• The Linux binfmt_misc driver needs shebang lines, despite the existence of file extensions, MIME-type xattrs, and shell file-association preferences tables
• Files marked as "quarantined" in macOS just look like regular files in the CLI, and no CLI program chokes on them, allowing scripted operations against such files to get quite deep in, until they hit some Cocoa-enabled subtask like codesign(8) that suddenly chokes on the quarantined input
I'm not totally sure on what a good solution to all this would look like, but I imagine it'd look like a replacement of all the custom kernel-to-userland callback APIs with a sort of "kernel-supported COM" where the kernel can talk to userland processes as if it were just another userland process making a COM request; and then the kernel can end up holding onto userland process COM object proxy-handles, passing them around, putting them into other kernel structs, etc.
Ideally, I think, the kernel would be responsible for declaring the contracts/interfaces that all shells running on that OS must implement themselves in terms of. Then "shell objects" would just be pure-userland kernel objects (i.e. defined by kernel base-classes, but with no kernel code in their codepath at runtime), sort of like Linux vDSOs are pure-userland kernel drivers.
Linux isn't really "ready" for this change—there are some gnarly legacy kernel-structs that need to retain their shapes and semantics, due to them being directly userland-visible without an intermediate view layer. But WinNt could totally do this, implemented almost entirely in terms of opaque kernel-object handles as it is. Nt-level structs don't matter one whit to userland, so they're free to be changed to retain opaque shel...
C++/CX was the closer that they got to it, and it remains to be seen how much complains are they willing to keep taking until C++/WinRT matches C++/CX tooling.
And I fully agree with you, C++ Builder and also Delphi have proven that such bindings were already possible 20 years ago, but for whatever reason there are some key devs (or management) at Microsoft that keeps pushing back for such productivity and brings out stuff like ATL/WRL instead.
I like COM/UWP, but boy some of the decisions just don't make sense.
This is how we used to write code, back in the day. If you had a particularly hard time and experimentation wasn't working well, you traced through the disassembly in the debugger.
Don't even get me started on the Java wrappers for ArcObjects... Thank god things have moved on.