Unable to run Wix Custom Action in MSI - wix

I'm trying to create a custom action for my Wix install, and it's just not working, and I'm unsure why.
Here's the bit in the appropriate Wix File:
<Binary Id="INSTALLERHELPER" SourceFile=".\Lib\InstallerHelper.dll" />
<CustomAction Id="HelperAction" BinaryKey="INSTALLERHELPER" DllEntry="CustomAction1" Execute="immediate" />
Here's the full class file for my custom action:
using Microsoft.Deployment.WindowsInstaller;
namespace InstallerHelper
{
public class CustomActions
{
[CustomAction]
public static ActionResult CustomAction1(Session session)
{
session.Log("Begin CustomAction1");
return ActionResult.Success;
}
}
}
The action is run by a button press in the UI (for now):
<Control Id="Next" Type="PushButton" X="248" Y="243" Width="56" Height="17" Default="yes" Text="!(loc.WixUINext)" >
<Publish Event="DoAction" Value="HelperAction">1</Publish>
</Control>
When I run the MSI, I get this error in the log:
MSI (c) (08:5C) [10:08:36:978]: Connected to service for CA interface.
MSI (c) (08:4C) [10:08:37:030]: Note: 1: 1723 2: SQLHelperAction 3: CustomAction1 4: C:\Users\NATHAN~1.TYL\AppData\Local\Temp\MSI684F.tmp
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 SQLHelperAction, entry: CustomAction1, library: C:\Users\NATHAN~1.TYL\AppData\Local\Temp\MSI684F.tmp
MSI (c) (08:4C) [10:08:38:501]: Product: SessionWorks :: Judge Edition -- 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 SQLHelperAction, entry: CustomAction1, library: C:\Users\NATHAN~1.TYL\AppData\Local\Temp\MSI684F.tmp
Action ended 10:08:38: SQLHelperAction. Return value 3.
DEBUG: Error 2896: Executing action SQLHelperAction failed.
The installer has encountered an unexpected error installing this package. This may indicate a problem with this package. The error code is 2896. The arguments are: SQLHelperAction, ,
Neither of the two error codes or messages it gives me is enough to tell me what's wrong. Or perhaps I'm just not understanding what they're saying is wrong.
At first I thought it might be because I was using Wix 3.5, so just to be sure I tried using Wix 3.0, but I get the same error.
Any ideas on what I'm doing wrong?

For your custom action assembly you need a config file and set the useLegacyV2RuntimeActivationPolicy attribute to true. Make sure you name your config file CustomAction.config. If you don't, it won't work. I am assuming you are running on the .NET 4 Framework.
See here for more info. Also, as AntonyW already pointed out, fuslogvw.exe is very helpful in this scenario.

instead of referencing the .dll reference the .CA.dll, it worked for me.

Custom Actions launched via DoAction are not able to write to the log file.
This confused me as well, when I first started using WiX.
If you want to see what is going on, you can use System.Diagnostics.Debugger.Launch() at the start of the Custom Action. This will prompt you to attach Visual Studio to the process so you can debug it.

For me, it was my CustomAction DllEntry did not match my method name. i.e.
<CustomAction Id="CheckingPID" BinaryKey="CheckPID.CA" DllEntry="BadValue" />
public static ActionResult CheckPID(Session session)

This error comes when you have installer project configuration/platform set to debug/x64 and custom action project configuration/platform set to debug/x86 repectively.
Correct the platform setting to build the projects for same platform
In my case changing platorm solved the issue.
Thanks
Yogesh

One more possible answer - you may have specified the right CA DLL, and specified the right method, but if the method is not decorated with [CustomAction] you will receive that error.

Have you tried changing the runtime library settings on the custom action DLL? The debug mode options /MDd and /MtD require debug versions of the C++ runtime in particular, which are not available on production machines (there is no redistributable license for them). If you use the /MD compiler option you might also need to install the Visual Studio C++ runtime version that you require on the users' machines, there is a merge module for that: C++ Redistributable package with WIX.

Related

Windows Installer does not install feature and does not report an error. (Request: Null)

A simple msi created using WiX. Trying to install a product. On some computers it will fail, without an error, and the installer log will contain these rows:
PROPERTY CHANGE: Adding WIX_UPGRADE_DETECTED property. Its value is '{7C9...0A0}'
PROPERTY CHANGE: Adding MIGRATE property. Its value is '{7C9...0A0}'
Product Code from property table after transforms: '{68F...FAE}'
Product not registered: beginning first-time install
Doing action: INSTALL
Doing action: InstallValidate
Feature: ProductFeature; Installed: Absent; Request: Null; Action: Null
MIGRATE = {7C9...0A0};{A9B...BCE}
Installation completed successfully.
Somehow, Windows Installer decides that there is nothing to do (Request: Null), even though it acknowledges that this is the first time install. That computer had previous version of the product installed. How do I force the installer to install?
Here is the relevant WiX code:
<Product Id="*"
Name="..."
Language="1033"
Version="..."
Manufacturer="..."
UpgradeCode="8D8...196">
<Package Id="*"
InstallerVersion="200"
Compressed="yes"
InstallScope="perMachine"
InstallPrivileges="elevated"
Platform="$(var.Platform)" />
<Property Id="REINSTALLMODE" Value="amus" />
<MajorUpgrade AllowDowngrades="yes" IgnoreRemoveFailure="yes" AllowSameVersionUpgrades="no"/>
<Feature Id="ProductFeature" Title="..." Level="1" Absent="disallow" AllowAdvertise="no" InstallDefault="local" TypicalDefault="install">
<Condition Level="1">True</Condition>
Full installer log: https://www.dropbox.com/s/abnryavh203a82w/acme_installer_log.txt?dl=0
You did not set MigrateFeatures in your MajorUpgrade element. The documentation says the default value is Yes.
http://wixtoolset.org/documentation/manual/v3/xsd/wix/majorupgrade.html
The log shows you are doing an upgrade, therefore the only features that are going to be installed is the same set that are already installed.
It's not clear how many features there are in your product, but if you always want all features to be installed during an upgrade set MigrateFeatures to No.
Either way, it would be better to supply the entire log to see what's going on and if there is another explanation.
This got too long for a comment, adding as an answer. Just a couple of things:
You definitely should not set REINSTALLMODE="amus" for any MSI package.
If you include merge modules in this setup you could downgrade shared files - even if you otherwise don't write to shared locations yourself.
The best would be the default "omus", but I guess "emus" is also ok (Reinstall if the file is missing, or is an equal or older version).
It certainly looks like the MigrateFeatureStates action is at least related to the problem seen:
MigrateFeatureStates: based on existing product, setting feature 'ProductFeature' to 'Absent' state.
Your INSTALLLEVEL property looks fine.
You might want to open the compiled MSI and verify that there are no entries in the Condition table (which can change feature selection states). There should be nothing there, but perhaps just verify.
I suppose you could try to set the Absent attribute for the WiX Feature element to "disallow", recompile and see if this changes things. If this is your only feature I would make this change in addition to using Phils suggestion to set MigrateFeatureStates to "No". Why allow your only feature to be removed?
It is a little odd how this problem has occurred. Perhaps you ran modify on your MSI and simply selected the feature to be uninstalled in the old installation on the machine? Sounds unlikely - especially if it is your only feature.
Did you install several earlier versions of your product on the machine in question, or was there only one prior version?
Again, are there entries in the "Condition table" in the compiled MSI? (Check using Orca).
Did you change the feature name in your newest package?
In any event you should be able to "fix" the broken install by 1) simply running your existing setup and adding ADDLOCAL=ALL to your msiexec.exe install command - I think that will override the MigrateFeatureStates action (not a real fix, just a workaround). Or 2) you can disable MigrateFeatureStates and recompile the setup - that should fix things permanently, and 3) if I were you I would set the Absent attribute for the WiX Feature element to "disallow" so that your (only?) feature can't be removed.
Phil, if you see this, do you know what the MIGRATE property seen in the log is about? It looks like some WiX specific stuff - unless it is something from this MSI's upgrade table:
MSI (c) (04:24) [13:01:38:751]: Doing action: FindRelatedProducts
MSI (c) (04:24) [13:01:38:751]: Note: 1: 2205 2: 3: ActionText
Action 13:01:38: FindRelatedProducts. Searching for related applications Found application: [1]
Action start 13:01:38: FindRelatedProducts.
FindRelatedProducts:
MSI (c) (04:24) [13:01:38:751]: PROPERTY CHANGE: Adding WIX_UPGRADE_DETECTED property. Its value is '{7C945F97-A2CC-4EEB-87AC-3D23D6C490A0}'.
MSI (c) (04:24) [13:01:38:751]: PROPERTY CHANGE: Adding MIGRATE property. Its value is '{7C945F97-A2CC-4EEB-87AC-3D23D6C490A0}'.
FindRelatedProducts:
MSI (c) (04:24) [13:01:38:752]: PROPERTY CHANGE: Modifying WIX_UPGRADE_DETECTED property. Its current value is '{7C945F97-A2CC-4EEB-87AC-3D23D6C490A0}'. Its new value: '{7C945F97-A2CC-4EEB-87AC-3D23D6C490A0};{A9B1787A-32E4-4D51-819D-B3F879574BCE}'.
MSI (c) (04:24) [13:01:38:752]: PROPERTY CHANGE: Modifying MIGRATE property. Its current value is '{7C945F97-A2CC-4EEB-87AC-3D23D6C490A0}'. Its new value: '{7C945F97-A2CC-4EEB-87AC-3D23D6C490A0};{A9B1787A-32E4-4D51-819D-B3F879574BCE}'.
Action ended 13:01:38: FindRelatedProducts. Return value 1.
tandrasz: as far as I can see the two GUIDs that are found by FindRelatedProducts ({7C945F97-A2CC-4EEB-87AC-3D23D6C490A0};{A9B1787A-32E4-4D51-819D-B3F879574BCE}), are different from your new setup's product code ({68F5E655-2E2D-492E-B445-BE1650AF5FAE}). This makes it look like there are two "related products" found by FindRelatedProducts on the machine in question. Are two older versions of the same MSI installed, or do you have a "suite" of MSI files that all share the same upgrade code?. If you have two "unrelated" packages installed, perhaps MigrateFeatureStates finds no way to migrate the feature states between those two and the new package you are installing?

Wix CustomAction with After='InstallFinalize' executed in upgrade to next version?

I am using the following code to start a Setup program at the end of my Installation (also with elevated permissions):
<Product ... >
...
<InstallExecuteSequence>
<Custom Action='LaunchSetupAction' After='InstallFinalize'/>
</InstallExecuteSequence>
<!-- Workaround required for Windows7, Setup.exe can not be started directly because of UAC
http://stackoverflow.com/questions/2325459/executing-a-custom-action-that-requires-elevation-after-install -->
<Property Id="WixShellExecTarget" Value='[#SetupEXE]'/>
<CustomAction Id="LaunchSetupAction" BinaryKey="WixCA" DllEntry="WixShellExec" Execute="immediate" Return="check" Impersonate="yes"/>
...
<MajorUpgrade DowngradeErrorMessage="A later version of [ProductName] is already installed. Setup will now exit." />
</Product>
This works well when then program is installed freshly, but when it is upgraded from a previous version with the same code, the installation reports a fatal error and fails.
In the Windows installer log I have found the following:
Action start 23:42:22: LaunchSetupAction.
...
MSI (s) (38:88) [23:42:22:342]: Invoking remote custom action. DLL: C:\WINDOWS\Installer\MSI679.tmp, Entrypoint: WixShellExec
...
WixShellExec: WixShellExecTarget is C:\Program Files\Me\MySetup.exe
...
WixShellExec: Error 0x80070002: ShellExec failed with return code 2
...
WixShellExec: Error 0x80070002: failed to launch target
...
Action ended 23:42:22: LaunchSetupAction. Return value 3.
Action ended 23:42:22: INSTALL. Return value 3.
Interesting enough these error messages (file not found?) is also there when I comment out the CustomAction in the new version of the installer.
Why is this CustomAcount executed from the previous version to be uninstalled?
Is there any way I can stop it from being run? After a certain point of the upgrade, the MySetup.exe is just not there anymore and will always cause a fatal error ...
That custom action has no condition on it, so it will be called on all types of installer operations, such as uninstall, add/remove features etc. Your upgrade is an install of the new product and an uninstall of the old product.
You need this kind of thing on your custom action:
Wix: Run custom action based on condition
so a condition of 'Not Installed' causes the CA to run only if the product is not already installed.
You can't really fix this because the uninstall for that product is embedded in the system. You'd need to fix that older version of the product by rebuilding the exact same product with the custom action condition fixed and then fix it with:
msiexec /i [path to new MSI] REINSTALL=ALL REINSTALLMODE=vomus
If you're very familiar with MSI and Orca, you may be able to locate the cached MSI file in C:\windows\installer, open it with Orca, go the InstallExecuteSequence and give that custom action a condition of 0, then save it. That basically corrects the uninstall sequence so that your upgrade will work. Caveat Emptor.
It also appears that a plain uninstall would give you same error - did you every try to do an uninstall test?

Module failed to register HRESULT / Error 1001

My first question is about the error below :
Module [Path/Name of dll].dll failed to register. HRESULT -2147024769. Contact your support personnel.
I can continue the installation but i want to get rid of this error if possible.
The second question is about the following error :
Error 1001. Exception occured when initializing the installation.
System.IO.FileNotFoundException: could not load file or assembly 'file:///C:\Windows\SysWOW64\files' or one of it's dependencies. The system cannot find the file specified.
I saw in different site and thread that the cause was the custom Action (in the value : /target=”[TARGETDIR]” -> /target=”[TARGETDIR]\”) but I can't found where is the error in my custom action. Here are the custom action realized using Designer for Wix Toolset :
<CustomAction Id="DIRCA_TARGETDIR" Property="TARGETDIR" Value="[ProgramFilesFolder][Manufacturer]\[ProductName]" Execute="firstSequence" />
<CustomAction Id="_FB3FF635_EF79_4863_91BD_70A0A11955B2.Uninstall" Execute="deferred" BinaryKey="InstallUtil" DllEntry="ManagedInstall" adx:VSName="Primary Output from Project" />
<CustomAction Id="_FB3FF635_EF79_4863_91BD_70A0A11955B2.Uninstall.SetProperty" Property="_FB3FF635_EF79_4863_91BD_70A0A11955B2.Uninstall" Value="/installtype=notransaction /action=uninstall /LogFile= /targ="[TARGETDIR]\" /usr=[ALLUSERS] /usr2=[MSIINSTALLPERUSER] /CommonProjAppData="[PROJCOMMONDATA]\" "[#_F521D169_ECD0_42B5_87F7_C2D8B6F9CA54]" "[VSDFxConfigFile]"" adx:VSName="Primary Output from Project" />
<CustomAction Id="_BE73DAD9_3524_4376_B45C_148B5871465B.Install" Execute="deferred" BinaryKey="InstallUtil" DllEntry="ManagedInstall" adx:VSName="Primary Output from Project" />
<CustomAction Id="_BE73DAD9_3524_4376_B45C_148B5871465B.Install.SetProperty" Property="_BE73DAD9_3524_4376_B45C_148B5871465B.Install" Value="/installtype=notransaction /action=install /LogFile= /targ="[TARGETDIR]\" /usr=[ALLUSERS] /usr2=[MSIINSTALLPERUSER] /CommonProjAppData="[PROJCOMMONDATA]\" "[#_F521D169_ECD0_42B5_87F7_C2D8B6F9CA54]" "[VSDFxConfigFile]"" adx:VSName="Primary Output from Project" />
<CustomAction Id="CA_CreateConfig" BinaryKey="ADXDPCADLL" DllEntry="GetConfig" />
Thanks for helping.
You're basically going in the wrong direction. You've converted a Visual Studio setup to WiX but you're trying to carry that VS custom action framework into WiX. The VS framework that calls managed code custom actions involves calling a C++ binary that then tries to load a NET runtime then use reflection to get into your assembly, instantiate classes and call methods. Apart from the fact that the InstallUtil Dll is transparent, undocumented and architecture dependent (you need either the 64-bit version or the 32-bit version) and therefore impossible to debug in cases like this, nobody actually bothers to propagate all this stuff into the WiX world because there are much better alternatives. For example if you're using installer classes to install services you don't need them at all. See ServiceInstall and ServiceControl. For generic custom action calls into managed code use the DTF managed code custom action framework.

WiX: Simple way to prompt user to install .NET pre-requisite

I currently have a working .msi built with WiX that has a user interface I'm quite happy with. The only thing missing is to detect for missing .NET 4.5 and either:
Install it using an embedded web setup, or
Direct the user to the .NET 4.5 download
The previous Setup and Deployment project I was using simply added it as a LaunchCondition with a URL and that worked well enough.
How can I add this to the WiX installer without resorting to a bootstrapper. From what I can tell using a bootstrapper like burn would require re-implementing a new user interface, likewise a tool like dotNetInstaller would also introduce a new UI.
If I can have the bootstrapper not implement it's own UI but trigger the .NET installation then open the msi's current user interface that would also work for me.
This is the code I ended up using... hasn't been through full testing yet!
Product.wxs:
...
<!-- custom actions -->
<InstallUISequence> <!-- .NET dialog runs only in UI mode and we skip it on the wrong platform so platform condition test is triggered later -->
<?if $(var.Platform) = x64 ?>
<Custom Action="InstallCA" Before="LaunchConditions">(NOT REMOVE~="ALL") AND NOT (Installed OR NETFRAMEWORK45) AND VersionNT64</Custom>
<?elseif $(var.Platform) = x86 ?>
<Custom Action="InstallCA" Before="LaunchConditions">(NOT REMOVE~="ALL") AND NOT (Installed OR NETFRAMEWORK45) AND NOT VersionNT64</Custom>
<?endif?>
</InstallUISequence>
</Product> <!-- end product -->
<Fragment>
<Binary Id="WiXCustomActions" SourceFile="$(var.WiXCustomActions.TargetDir)$(var.WiXCustomActions.TargetName).CA.dll" />
<CustomAction Id="InstallCA" BinaryKey="WiXCustomActions" DllEntry="DotNetCheck" Execute="firstSequence" />
</Fragment>
And the custom action (in a C# class library):
[CustomAction]
public static ActionResult DotNetCheck(Session session)
{
try
{
MessageBoxResult result = System.Windows.MessageBox.Show(
"This application requires that .NET Framework 4.5 is installed." + Environment.NewLine
+ "Would you like to open the Microsoft download page for" + Environment.NewLine + ".NET Framework 4.5?",
".NET Framework 4.5 is missing",
MessageBoxButton.YesNo, MessageBoxImage.Information, MessageBoxResult.No, MessageBoxOptions.DefaultDesktopOnly);
switch (result)
{
case MessageBoxResult.Yes:
System.Diagnostics.Process.Start("http://go.microsoft.com/fwlink/p/?LinkId=245484");
break;
} //else just finish
}
catch (Exception ex)
{
session.Log("Error. " + ex.Message);
System.Windows.MessageBox.Show("Error:" + ex.Message);
}
return ActionResult.SkipRemainingActions;
}
It works good enough for me...
I also wanted to keep the UI from the MSI so I added this code to start an exe installer for hardware keys. I know it goes against MSI Best Practices but this is the only one I intend on breaking. Hope this helps.
<Property Id="WixShellExecTarget" Value="[#myapplication.exe]" />
<CustomAction Id="LaunchApplication" BinaryKey="WixCA" DllEntry="WixShellExec" Impersonate="yes" />
I then ran the custom action from a button click. You could spawn an error dialog with a download button on it and link it via that. Not very elegant at all but it works for me and my company as a work around..:)
EDIT: you could also use this code from a button click to launch the URL for the download, the Value attribute having the full hyperlink.
And one important things, when you will be creating this DLL lib
And the custom action (in a C# class library):
Need to add next References:
using WixSharp
using Microsoft.Deployment.WindowsInstaller
using System.Windows.Forms
also replace "MessegeBoxResult" to "DialogResult" and MessegeBox should get from class System.Windows.Forms

WiX close application before uninstall - close open applications message

I'm in a kind of misery. I got an installer installing and starting a tray icon app (common .exe)
This is working properly, but now i want to stop that app before this UI telling the user to close the app manually comes up, because during the deinstall routine, my tray icon is removed but the process is still running.
I applied this custom action to close the app before uninstall (or even during)
<CustomAction Id="CloseTrayApp" ExeCommand="-exit" FileKey="TrayApp" Execute="immediate" Return="asyncNoWait" />
<InstallExecuteSequence>
<Custom Action="CloseTrayApp" Before="InstallValidate" />
</InstallExecuteSequence>
But the "close all running apps" dialog still pops up, but i thought that this will solve my issue.
I already tried to use the CloseAction but i got into a hurry using it because of error while compiling the stuff. It says that the WixUtils namespace may be missing but i double checked that it is there:
xmlns:util="http://schemas.microsoft.com/wix/UtilExtension"
How can I avoid the dialog window poping up and trigger this custom action to be executed?
You also have to add a reference to WixUtilExtension.dll. If you are using Visual Studio / Votive you just right click add reference and select the DLL from [ProgramFilesFolder]Windows Installer XML v3.5\bin. Otherwise you have to make the extension available to the compiler and linker:
candle.exe yourfile.wxs -ext %full path to WixUtilExtension.dll%'
light.exe yourfile.wixobj -ext %full path to WixUtilExtension.dll% –out yourfile.msi yourfile.wixout'
More information can be found at:
Using Standard Custom Actions
Please note that the CloseApp custom action has a limitation that it won't "terminate" your application. It will only politely send your app a WM_CLOSE message and it's up to your trayapp to receive and process that message with a shutdown.