When .NET first came out, "write once run everywhere" idea presented a lot more value. There were a lot more CPU architectures being used in business. (The old Unix vendors and their proprietary RISC architectures were waning by then, but were still a force in the industry - see Java.) Macs were still running on PowerPC. And the PC platform itself was looking like it might take a turn for the hetrogeneous. IA-32 was still dominant, but the need to move toward 64 bit had been recognized. Intel's answer, Itanium, was a completely different architecture that came out less than a year before .NET hit the market. AMD64 had been announced and was expected to hit the market fairly soon. With Windows computers having a choice among three different architectures that weren't binary-compatible, and the possibility that enterprise customers might still end up sticking with SPARC or MIPS for the long haul, the bytecode option probably was the most strategic option for Microsoft at the time.
Even now, having an intermediary binary format's still fairly valuable. I could conceivably get a component from a vendor and put it into production on a slew of different platforms - Intel chips running Windows, Linux and OS X, phones with A5 or ARM chips, etc. without having to mess around with source code distributions, other people's funky build configs, etc. The ones going on smartphones would eventually be native-compiled, but getting bytecode binaries means I don't need to fiddle with separate native binaries for different target platforms.
It's also worth noting that what the Java and .NET platforms have achieved in terms of language interoperability hasn't really been matched by interpreted and native-compiled languages. That's arguably a result of culture rather than any sort of technical limitation. OTOH, the technical limitation that the .NET and Java virtual machines define object formats, function signatures, and whatnot does go a long way in facilitating interoperability.
Finally, the .NET and Java assembly languages are dead easy to target, especially compared to those of complex architectures like x86. Even if shipping native binaries becomes dominant in the .NET space, MSIL won't be going away. And it makes everyone's life easier to not have to reinvent the "native code generation" wheel for every possible programming language/CPU architecture pairing. LLVM's a big deal for the same reason, and to some extent the only really big difference between it and .NET or Java is that it doesn't encourage people to package bytecode up into executables.
Even now, having an intermediary binary format's still fairly valuable. I could conceivably get a component from a vendor and put it into production on a slew of different platforms - Intel chips running Windows, Linux and OS X, phones with A5 or ARM chips, etc. without having to mess around with source code distributions, other people's funky build configs, etc. The ones going on smartphones would eventually be native-compiled, but getting bytecode binaries means I don't need to fiddle with separate native binaries for different target platforms.
It's also worth noting that what the Java and .NET platforms have achieved in terms of language interoperability hasn't really been matched by interpreted and native-compiled languages. That's arguably a result of culture rather than any sort of technical limitation. OTOH, the technical limitation that the .NET and Java virtual machines define object formats, function signatures, and whatnot does go a long way in facilitating interoperability.
Finally, the .NET and Java assembly languages are dead easy to target, especially compared to those of complex architectures like x86. Even if shipping native binaries becomes dominant in the .NET space, MSIL won't be going away. And it makes everyone's life easier to not have to reinvent the "native code generation" wheel for every possible programming language/CPU architecture pairing. LLVM's a big deal for the same reason, and to some extent the only really big difference between it and .NET or Java is that it doesn't encourage people to package bytecode up into executables.