Most Windows apps ship with copies of all their dependencies. The DLL Hell problem was solved by disk and bandwidth getting cheaper to the point where many dozens or even hundreds of copies of MSCVRT.DLL and friends on your system pass unnoticed.
If you absolutely need a way to install dependencies globally such that they can be shared between apps, you can still do that without version conflicts if you write proper manifests for them and use https://en.wikipedia.org/wiki/Side-by-side_assembly.
But it's easier to just package a local copy and not worry about any of this, so that's what people mostly do now.
But isn't that a good thing? I don't mind having more DLLs if stuff just works. It avoids the similar, though harder to solve issues on Linux. I'd rather be able to have a copy of the MSCVRT.DLL than to have to pray that my system has the right glibc to be honest.
But maybe I'm not understanding the trade offs correctly.
> I don't mind having more DLLs if stuff just works.
The counterpart is when a remotely exploitable security issue is found in that DLL, as has happened with zlib in the past and log4j more recently; then you have to chase down and update every single copy of that DLL.