There is a property in Add/Remove Programs (called "Programs and Features" in Vista+ but setup developers in the know call it "ARP") that can specify the install location for your application. Like most properties in ARP, it's questionable what value InstallLocation provides. However, it's there and some things look for it and the Windows Installer provides a standard way to set it, so let's talk about how to do so with the WiX toolset.
The Windows Installer standard property for setting the ARP install location is named ARPINSTALLLOCATION. Like many things in the Windows Installer, the name is pretty obvious but setting the value correctly requires extra work. In this case the documentation provides the hint, "Typically needs to be set by a custom action".
I think the word "typically" in that sentence is a little misleading. You have a weird installer if you do not need a custom action. Even "custom action", while technically correct, sounds scarier than it really is.
Anyway let's look at what you really need to do in WiX v3+, and we'll dissect why afterwards:
<SetProperty Id="ARPINSTALLLOCATION" Value="[ApplicationFolder]" After="CostFinalize" />
Each word there is important, so let's break them down:
SetProperty - this element is syntactic sugar in the WiX toolset to create a Type 51 custom action. As you might guess from the sugar's name, Type 51 custom actions assign a value to a property. Type 51 are the custom actions that I don't consider custom actions. They are really just assignment statements (i.e. x="y") at setup time.
We need an assignment statement in this case because the install location is not known until we install. Even if your install is hardcoded to install to ProgramFilesFolder, we won't know if that is on the C: drive or D: drive or even the name of the folder (because ProgramFilesFolder is localized).
Id="ARPINSTALLLOCATION" - this attribute is hopefully self-explanatory. We're going to be setting the property with the name ARPINSTALLLOCATION. This is why we are here. If you forgot, I highly recommend re-reading the first three paragraphs.
Value="[ApplicationFolder]" - this attribute contains the formatted value we want assigned to the property. The formatted part is the most important. Formatted means the Windows Installer will resolve things in square brackets to their setup time value according to the formatted topic in the Windows Installer (I recommend bookmarking it).
In this case, ApplicationFolder is the Directory/@Id where my application is being installed. I've standardized on this name for my application's directory in the last few setup projects I've done. You should use whatever value maps to the directory identifier for you application's setup.
After="CostFinalize" - this attribute is pure magic. If you read the whole MSI SDK, eventually you'll read about the CostFinalize Action. When you do, you are sure to notice this very important sentence, "The CostFinalize action must be executed before starting any user interface sequence which allows the user to view or modify Feature table selections or directories." Essentially, that tells us that the earliest the directories can be resolved (like through a formatted value) is after CostFinalize completes.
Oh, look! We scheduled the assignment of the ARPINSTALLLOCATION property after CostFinalize so that the ApplicationFolder would be resolved and return the full path to the application's directory.
Great, we're done. Right? Well, what I've presented here will work just fine. But there is one optimization that we can make that will also add a bit more correctness as well. Do you see it? If not, next week I'll post the optimization and why what I said in the previous paragraph isn't perfectly correct.
In the mean time, keep coding... you know I am.