W3bbo wrote:
...but I was under the impression .NET Application Assemblies (.exes) were portable, the only thing that mattered being the JIT-C program on the client.
They are. It's just that, for backwards compatibility with Windows 9x, NT 4.0 and 2000, Microsoft chose to reuse the existing executable format, making it very easy for existing programs to naively load .NET programs. The way the loading works is a kludge: the executable's import table refers to _CorExeMain in mscoree.dll (_CorDllMain for /t:library), then the start address in the executable header is set to point to that address in the import address table. At launch time, the loader loads mscoree.dll, fills in the address of _CorExeMain in the IAT, then jumps to the start address - which is now just a jump instruction to the start of _CorExeMain.
There are some clever tricks in .NET 2.0 to ensure that, if appropriate, the executable ends up loaded in a 64-bit process.
For Compact Framework, an executable is still marked as being for the x86 processor family and using the Windows GUI (or console) subsystem. I'm not quite sure how that works. Presumably the loader's been patched to anticipate it and recognise the executable properly.
W3bbo wrote:
But if the .exe is in PE format, how do you run these under MONO on UNIX or Mac?
By running the mono executable, passing the .exe as the first command line argument. Presumably the OS loaders and shells have not been modified to recognise PE format executables natively.
W3bbo wrote:
...unless MONO recognises the header or something?
You could, of course, register the .exe extension with whatever shell you're using, to make it launch mono passing the .exe name as a command line argument.