Reputation: 41
I have already achieved a custom command without dependence without any problem.
But here it is a custom command that need to be link with four other dll to work.
<Binary Id="libeay32" SourceFile="..\bin\libeay32.dll"/>
<Binary Id="libintl" SourceFile="..\bin\libintl.dll"/>
<Binary Id="libpq" SourceFile="..\bin\libpq.dll"/>
<Binary Id="ssleay32" SourceFile="..\bin\ssleay32.dll"/>
<Binary Id="custom" SourceFile="..\bin\custom_cmd.dll"/>
<CustomAction Id="cc_postgres" BinaryKey="custom" DllEntry="on_postgres_cmd" Execute="immediate" Return="check" HideTarget="no" />
I got the following error at installation
Error 1723. There is a problem with this Windows Installer package. A DLL required for this install to complete could not be run. Contact your support personnel or package vendor. Action cc_postgres, entry: on_postgres_cmd, library: C:\Users\THE\AppData\Local\Temp\MSI17BB.tmp
How doing this spot in Wix, without recompile everything in static.
Thx.
Upvotes: 4
Views: 2482
Reputation: 213
MSI does not provide these services, and WiX does not offer an extension to do so. You could, I suppose, write a WiX extension for this purpose, but why?
MSI runs your Type 1 custom action by first extracting a copy of the Binary resource to a temporary directory, then invoking the entry point in that copy, and (upon completing the custom action) releasing the temporary DLL copy. (Or not: MSI might decide to keep that copy around for a little while, as an optimization in case you're going to call some other entry point later. But that's up to MSI, not to your code.)
The key point is that the Binary resource is auto-loaded temporarily... and only the one resource. That means it is up to your custom action to load any other resources needed.
Your custom action would, as its first steps, need to open a view on the Binary table, read the Data column from the appropriate record as a stream, and dump that data buffer to a file somewhere, then do an explicit ::LoadLibrary()
. Then ::GetProcAddress()
on the function(s) your custom action will call from that loaded library, and use the fetched pointer(s) to do the explicit call(s). Finally, since you are a courteous programmer, when your custom action is done, it needs to tear all this infrastructure down before returning: release the view and library handles, delete the temporary files, etc.
If all this seems a lot of hassle, you're right, it is. The very simple solution is exactly the one you reject: link your custom_cmd.dll
statically. Yes, that will make your binary, and the .msi which contains it, a little bit larger (and not that much larger, since you may no longer need separate Binary copies of the dependent DLLs). But that's pretty much the only downside. The upside is that your custom action carries along with it everything it needs to get its job done.
I routinely do a static link on any binaries -- not just custom actions, but bootstrappers, etc. -- that run at install time, even if they don't have explicit external dependencies. (But of course they have implicit ones, like the Visual C++ runtime libraries, etc.) That way, I not only know I have the resources I need, but the right version of those resources, and not whatever version the customer may have happened to install previously... or not have installed at all.
Your install package is a scout who does not know his environment ahead of time. It might be a big American city... or it might be the Moon. Or Barsoom. Don't presume that you will have cell-phone service... or oxygen. Carry it with you!
Upvotes: 4