Let me start by saying I'd love to get people's feedback on the content of this post...
When Toyota designs a car they would never ignore the fact that no matter how great a car they build, they have to be able to get it to their customers. Additionally, they have to be able to get it to them at a reasonable cost. Imagine that Toyota decided that it would be cool to create a car that is 4 seats wide. Assume they ignored that the world's infrastructure is built to handle cars two seats wide. Can you imagine what would happen if they did that? Cars wouldn't fit on boats, on trucks, in garages, etc. In short, the cars would sit at the factory. Assuming the world wants the car people would scramble to create the infrastructure to get the cars to the users. In the end all of this would drive up the cost of shipping the cars and cause customers to pay more money to get it.
Software is no different
Unfortunately, software is often designed without considering its ship vehicle. What usually matters to developers is that it runs on their machine. It is designed and built until it works and is tested. Only then is deployment thought about. At that point, the application usually does tons of things that make software deployment a nightmare and costs way more that it would have if it were considered up front.
There's a way out
The standard for deployment on Windows is the Windows Installer (MSI). Luckily, for the applications that think about deployment last, Windows Installer is very extensible. If you want to run a bunch of custom code during install, you can. Having to do this is usually a sign that your application was not designed to make your deployment simple. You have to build a bunch of infrastructure as a band-aid for something that could have likely been avoided. Your custom code inevitably wont behave properly in some scenarios causing your entire deployment to become fragile. Whenever you see this, consider an upstream design change. This is more likely feasible if you aren't just about to ship your product and you aren't scrambling to build an installer package.
Make it simple
Setup can be really simple. Everything on a machine boils down to very simple things: Files, registry keys, and shortcuts. Windows Installer happens to handle Files, registry keys, and shortcuts very well. It's actually really easy to use if all you need to do to deploy your application is copy files, write registry keys, and add shortcuts to the system.
Its often not your application's fault
IIS did not make it easy to copy files to a location to install a web site. .NET didn't make it easy to GAC an assembly or NGEN it by copying it to a location. Both of these are things I like to call custom stores. Applications that expect other applications to extend them or use them as a platform need to be even more conscious of the deployment problems they cause. When platforms don't consider what it will take to deploy on top of them they make every one of their customers building solutions has to modify their shipping container to handle their custom store. Although we cant get rid of the custom stores that have already shipped, we can hopefully prevent more and more custom stores from being produced. I think people building on top of platforms should push back more when their platforms create more and more custom stores.
Start development with deployment
When building your applications, think about deployment as you design your app. Think, "Can I put this on my customers machine by only copying files"? If it starts to get hard, don't just write custom code to solve it. Think, "Could my application make itself easier to deploy?" Ideally, you could build your application to a folder and just run it without any configuration steps. You should create an empty installer package at the beginning of your project and build it up as you ad functionality to your product.
Application virtualization is on the horizon
If you make your application deployment completely declarative where no custom code has to run on your customers machine, your application will fit into the virtualized application world much better. It will also allow scenarios like drag and drop deployment, running from USB key.
Many of the things I've said as far as guidance are optimistic. The world isn't as clean as I wish it were. But in the end, I dont think we'll ever be in a better situation unless people start thinking about the problems and stop making things worse for the Windows eco system by creating custom stores in platforms that are not installer friendly.
This was originally posted here and may have additional comments.