ARPINSTALLLOCATION and how to set it with the WiX toolset.

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.

 

7 Comments

Comment by Christopher Painter on Friday, January 14, 2011 4:46 PM

I'll refrain from answering to keep the suspense. Deal?

Comment by Alasdair King on Monday, January 17, 2011 3:05 AM

There are two advantages: one is that you need to set ARPINSTALLLOCATION for Microsoft Logo certification (I know, that's a circular argument!) and the other is that you can then use the MSI scripting interface/API to get the installation folder for a program if you know its ProductCode, which is handy in all sorts of maintenance operations. Unless there's something much much simpler, in which case I'd love to know about it...

Comment by umesh on Friday, January 21, 2011 4:23 AM

Hi,

In the older installations our product did not save the install directory. In later version it was saved in the registry under a key devoted to our product. Neither versions had ARPINSTALLLOCATION. Is it possible to obtain it programmatically so an upgrading user can be told that an upgrade will take place at the installed location. (By specifying the path of existing location..)?

MSI knows this because it is able to uninstall previous versions through the RemoveExistingProduct action.

Comment by Steve Hidem on Wednesday, January 26, 2011 7:24 AM

I think the hint for the optimization lies in the statement "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.". I won't say anymore for now.

Best regards. I've enjoyed working with WiX.

Comment by Neil Sleightholm on Tuesday, February 01, 2011 9:38 AM

I should really know but what was the "optimization"?

Comment by Rennie on Monday, February 14, 2011 11:01 AM

I too would like to know about the "optimization".

Thanks for all your efforts with WiX.

Comment by Alexey Ivanov on Wednesday, April 06, 2011 1:32 AM

Isn't CostFinalize too early to remember the install location? Users can change the install location in the UI, so I'd think ARPINSTALLLOCATION should be set after UI wizard part is complete, just before installation starts.

Leave a comment
optional