Ah, I remember this realization. Cried like a baby for two days.

I ended up using Xenocode's PostBuild. They also can do virtualization and they have a code profiler (which I haven't used yet). I actually can't remember why I chose it over others, except that I couldn't get Dotfuscate to work. It works well now. I'm actually using it to encrypt all the strings in the app and haven't noticed any performance hit. It takes a while to figure out what you can and can't obfuscate, but eventually things calmed down.
I haven't used virtualization yet because while you simplify deployment, you also make it more complicated if you have a somewhat sophisticated app. I.e. By putting everything into one gigantic exe, you have now made the requirement that EVERY change to the application requires this gigantic Exe (of course, if it isn't gigantic, then this doesn't apply...of course, since the .NET stuff is included, this will likely be larger rather than smaller). By leaving the app as separate dlls, you at least have the possibility to update just one dll. My app is about 20mb, in an exe and 9 dlls. I have a base dll, a businessobjects dll, a UI dll, and the rest are in support of modules of the program. Often an update will be just 1 or 2 dlls. Since all of my users are remote (OK, I think 1 is inside the network), smaller updates is very important for my app.
This does required that you understand how .net handles assembly references. This is why SF is on 1.6.1, but I believe the dlls all say 1.6.0. By doing this they don't break anything.
Anyway, just some food for thought. Good luck on your quest!
Greg
The Other Former Access User