The help files could really use some serious work however since I had to find out how to do some simple tasks by trial and error.
Like others here all I wanted to do is remove some existing files from the target installation folder before they were copied by the installer. As most people have found out, if the same files already exist AI does not overwrite them. Remember: not all people have been using a proper installer prior to using AI so there's no guarentee how those files got there.
Its obvious that a custom action is required although I think this is an obvious candidate for a checkbox in the install parameters. The trick is to get the custom action to work which many people in this forum seem to have trouble with.
The problem is: how to get the TARGETDIR. I read the FAQ and saw the "all actions are deferred" comment and almost had a coronary! Then I did some playing around and found that this was either an old FAQ or they were only kidding
The trick is to make an "immediate" custom action that takes as a parameter the TARGETDIR. The rest is up to the custom action itself but that's nto to hard since its probably a DLL or something that has full access to the target machine.
Okay, enough preamble. Here's what you do (v2.4.1 only):
1. Click on Project Details->Custom Actions. You'll see the usual 4 suspects: Uninstall, Rollback, Install, Commit. None of these is any use to you so forget about them for now.
2. Right click on "Target Computer" and select "Show Standard Action". There's a LOT of standard actions and you can pick the one that suits the custom action best. In my case I just picked "Begin" which means my action will happen before anything else. Its probably a lazy choice but oh well...
3. The standard action you clicked should now show up on the list as a 5th item. You can now add custom actions to this item.
4. Right Click on the new Standard Action item you just added and select "New Attached Custom Item". (It doesn't have to be attached but that's the way I'm doing it in this example). You can now pick any file you want to attach. In this example I'm using a DLL so I pick "Setup.dll" which I wrote.
5. Once the Custom item item is added you'll have to set the properties on the right to match your action. In this case the "Source Type" was a DLL and the "Function Name" was whatever exported function I exposed in my DLL.
6. Here's where some documentation would really have been nice. I want to pass a parameter to my function: the Target Directory. I already discovered that MsiGetTargetPath() does not work so I have to pass it manually. Click the "Edit" button to the right of the Function Name field.
5. It gets even stranger as the window that come up says "Edit Custom Action Parameters" but the function name is already on this field. You'd be tempted to select a parameter for your DLL and press OK. Don't even bother pressing the "Help" button here as the help that comes up is worse than useless . *Sigh* Suffice it to say that this dialog seems to be only useful for building a command line for .exe custom actions. I suspect the AI programmers got a little tired at this point and didn't want to put too much effort into this dialog. We've all been there so I don't blame them but a few docs would have helped.
6. This is where it gets a little wierd. I tried all combinations of selecting parameters for my DLL and kept getting errors at runtime. From what I can tell this dialog is of little use for DLL's except to determine the Property Name of the parameter. In our case the property we're interested in is: TARGETDIR. Mostly by accident I discovered that you don't select anything from this dialog, just record the name of the property and leave your function name as the only entry in the field.
7. Now it comes time to actually get that parameter from within your function. This wasn't that hard to figure out once I figured out #6. Instead of MsiGetTargetPath() you want to use MsiGetProperty() with "TARGETDIR" as the Property Name. My DLL function looked something like this:
Code: Select all
int APIENTRY RemoveOld(MSIHANDLE hInstall)
{
char Path[MAX_PATH];
DWORD length = sizeof(Path);
UINT status;
CloseAll();
status = MsiGetProperty(hInstall, "TARGETDIR", Path, &length);
MessageBox(NULL, Path, "My DLL", MB_ICONINFORMATION);
// Note: Return non-zero for testing only!!!
return 1;
}
I hope this helps some people. I'm by no means an Windows Installer nor an AI expert so if anyone notices any errors I'm sure I have made in this document please post them for others to benefit.