How to execute a WiX custom action C++ DLL file with dependencies? - wix

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.

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!

Related

Optionally leave old version of component on upgrade

I've been trying to set up a WiX component such that the user can specify that the installer should not upgrade that component on a MajorUpgrade. I had the following code, but this means that if the condition is met then the new version is not installed, but the old version is also removed.
<Component Id="ExampleComponent" GUID="{GUID here}">
<Condition>NOT(KEEPOLDFILE="TRUE")</Condition>
<File Id="ExampleFile" Name="File.txt" KeyPath="yes" Source="File.txt"/>
</Component>
Ideally, if the user specifies "KEEPOLDFILE=TRUE", then the existing version of "File.txt" should be kept. I've looked into using the Permanent attribute, but this doesn't look relevant.
Is this possible to achieve without using CustomActions?
A bit more background information would be useful, however:
If your major upgrade is sequenced early (e.g. afterInstallInitialize) the upgrade is an uninstall followed by a fresh install, so saving the file is a tricky proposition because you'd save it, then do the new install, then restore it.
If the upgrade is late, then file overwrite rules apply during the upgrade, therefore it won't be replaced anyway. You'd need to do something such as make the creation and modify timestamps identical so that Windows will overwrite it with the new one. The solution in this case would be to run a custom action conditioned on "keep old file", so you'd do the reverse of this:
https://blogs.msdn.microsoft.com/astebner/2013/05/23/updating-the-last-modified-time-to-prevent-windows-installer-from-updating-an-unversioned-file/
And it's also not clear if that file is ALWAYS updated, so if in fact it has not been updated then why bother to ask the client whether to keep it?
It might be simpler to ignore the Windows Installer behavior by setting its component id to null, as documented here:
https://msdn.microsoft.com/en-us/library/windows/desktop/aa368007(v=vs.85).aspx
Then you can do what you want with the file. If you've already installed it with a component guid it's too late for this solution.
There are better solutions that require the app to get involved where you install a template version of this file. The app makes a copy of it that it always uses. At upgrade time that template file is always replaced, and when the app first runs after the upgrade it asks whether to use the new file (so it copies and overwrites the one it was using) or continue to use the existing file. In my opinion delegating these issues to the install is not often an optimal solution.
Setting attributes like Permanent is typically not a good idea because they are not project attributes you can turn on and off on a whim - they apply to that component id on the system, and permanent means permanent.
I tried to make this a comment, it became to long. I prefer option 4 that Phil describes. Data files should not be meddled with by the setup, but managed by your application exe (if there is one) during its launch sequence. I don't know about others, but I feel like a broken record repeating this advice, but hear us out...
There is a description of a way to manage your data file's overwriting or preservation here. Essentially you update your exe to be "aware" of how your data file should be managed - if it should be preserved or overwritten, and you can change this behavior per version of your application exe if you like. The linked thread describes registry keys, but the concept can be used for files as well.
So essentially:
Template: Install your file per-machine as a read-only template
Launch Sequence: Copy it in place with application.exe launch sequence magic
Complex File Revision: Update the logic for file overwrite or preservation for every release as you see fit along the lines as the linked thread proposes
Your setup will "never know" about your data file, only the template file. It will leave your data file alone in all cases. Only the template file it will deal with.
Liberating your data files from the setup has many advantages:
Setup.exe bugs: No unintended accidental file overwrites or file reset problems from problematic major upgrade etc... this is a very common problem with MSI.
Setup bugs are hard to reproduce and debug since the conditions found on the target systems can generally not be replicated and debugging involves a lot of unusual technical complexity.
This is not great - it is messy - but here is a list of common MSI problems: How do I avoid common design flaws in my WiX / MSI deployment solution? - "a best effort in the interest of helping sort of thing". Let's be honest, it is a mess, but maybe it is helpful.
Application.exe Bugs: Keep in mind that you can make new bugs in your application.exe file, so you can still see errors - obviously. Bad ones too - if you are not careful - but you can easily implement a backup feature as well - one that always runs in a predictable context.
You avoid the complicated sequencing, conditioning and impersonation concerns that make custom actions and modern setups so complicated to do right and make reliable.
Following from that and other, technical and practical reasons: it is much easier to debug problems in the application launch sequence than bugs in your setup.
You can easily set up test conditions and test them interactively. In other words you can re-create problem conditions easily and test them in seconds. It could take you hours to do so with a setup.
Error messages can be interactive and meaningful and be shown to the user.
QA people are more familiar with testing application functionality than setup functionality.
And I repeat it: you are always in the same impersonation context (user context) and you have no installation sequence to worry about.

wix burn custom bootstrapper - custom compiler extension

I have a custom bootstrapper using burn, in which I have to detect the driver version of a specific printer on startup and store this value in a burn variable for later usage. Until now, I did this in the overriden Run method of BootstrapperApplication, but I would rather create a WixExtension, to be able to do something like this:
<customUtil:PrinterDriverVersion PrinterName="somePrinter"
Variable="variableToStoreVersionValue" />
This would be similar to the RegistrySearch element in wix's UtilExtension.
There is an example of a CompilerExtension in the book "WiX 3.6: A Developer's Guide To Windows Installer XML", but I don't get it. Why do I need a new msi table? I just want to use that in burn, not in an msi installer?
I looked at the source code of wix, trying to understand, how the RegistrySearch element works. So UtilCompiler just parses the xml attributes and then creates some rows in the WixRegistrySearch table. This table gets iterated by the binder, who writes all searches in the BurnManifest and then creates the resulting output file (.exe). But when and where do this searches get executed at runtime?
Is a CompilerExtension capable to get my task done, or am I on the wrong way?
WiX doesn't have this functionality today. This use case is also needed for the VSExtension to support installing VSIX packages into VS2017 with a bundle, since code needs to be executed to detect VS2017 instances. I created a feature request here.
The UtilExtension searches are special. As you said, they end up in the BurnManifest. The code that executes the searches is in the Burn engine.

DTF is copying custom action dll files

I have msi setup that was created in installshield and I am executing the DTF custom action dll as a commit custom action. If I insert MessageBox.Show into the custom action, I can see that there is a temporary folder inside [PROGRAMFILESDIR] called "CustomActionProject.CA.dll-" and there is copied CustomActionProject.CA.dll with all its references.
Is there any way to tell the technology not to create this temp folder and extract+execute the CustomActionProject.CA.dll in the same folder where is .CA.dll located?
Edit:
I found out that I can not include the references in .CA.dll by configuring wix.ca.targets. Which prevents .CA.dll to contain 20MB of dlls in my case.
Now I would like to make sure that CustomActionProject.dll will be able to see the references that are installed with the product.
The files are:
<ProgramFilesFolder>
<MyApplicationFolder>
CustomActionProject.CA.dll
... About 30 dlls installed with the application that CustomActionProject.dll needs to call
<Place I Would Like to See CustomActionProject.dll extracted>
DTF automatically extracts it's files to a temp folder for execution and then cleans up on disposal. This is very good in that it eliminates certain race conditions. You can still author those files into your installer if you like. For example, at a previous company, our installer used several DLL's for license checking during the install and installed them for use by the application at runtime.
BTW, make sure you've seen this:
WiX DTF Behavior Alert
Your custom action was programmed in a managed .Net language (probably C# or VB.Net). As msi files may only contain dll custom actions comprised of native code the DTF tools, specifically the tool makesfxca.exe, packs / wraps the managed dll together with helper code resulting in a self extracting, native code dll. Following WIX´s naming convention the native custom action dll contains an .CA infix.
In order for this (i.e. having custom actions written in languages producing managed code) to work, self extraction has to take place. So the short answer to your question is "No".

run script of batch file from within WIX

I implement wix to generate some msi. I'd like to maintain .bat file (that is packed within this wix project) to contain some work to do (and to be activated with some custom action)
I added the .bet to my wix project in VS2010.
My question is
how do I actually wrap it within the msi that on target machine the script will be available to run?
How do I actually refer to that embedded batch file in the custom section element
This might not be the answer you're looking for, but I strongly recommend you NOT going this way. Running batch file from inside the MSI package has a number of disadvantages, which will shoot you one day:
antivirus might block the execution
as for any deferred custom action (the one which changes the target system state) you'll have to create a rollback action, and for a batch file which might include a number of steps of different nature it could be much more difficult
you don't have the progress (I doubt this is at all possible for batch script)
Instead, I encourage you to do the following:
analyze your batch script and make a list of exact things it does to the target system
take a look at the standard Windows Installer functionality and WiX extensions to see what's there out of the box
design your installation to use standard functionality as much as possible and custom actions as little as possible
if you still need a custom action, stick to the DLL ones and make sure rollback actions are present for deferred actions
You're looking for what I think is a type 18 custom action:
The executable is generated from a file installed with the application. The
Source field of the CustomAction table contains a key to the File table. The
location of the custom action code is determined by the resolution of the target
path for this file; therefore this custom action must be called after the file
has been installed and before it is removed.
The CustomAction element has the ExeCommand attribute for just this sort of occasion. It would look something like this:
<CustomAction Id="ExecuteMyBatchFile"
FileKey="[#FileKey]"
ExeCommand="Arguments passed to batch file"
Execute="deferred"/>
Of course, this is assuming the batch file is installed by the msi.

Registering DLL's in Wix using self-registration

Two of my library depends on the third. But the latter library must be copied to the system32 directory, another two - to the ProgramFiles directory. PLease could anyone advise on how to deal with registration of the first two libraries. I need to use self-registration. I tried to specify the id of the main library as a companion file, but it did not help. What should I do?
MSI's SelfReg table doesn't support ordering the operation of registrations. You could use the QuietExec custom action to call regsvr32 /s in the right order but I wouldn't do it myself.
The optimal design is to not rely on self reg. Have you thoroughly exhausted using MSI to handle the registration data for you as it was designed to do?