WIX Installer getting Bad condition and sequence error - wix

I want my custom action to be executed after the complete installation is been done. Went through so many sites but didn't get it work.
<Binary Id="DepTypeCustomActionBinary" SourceFile="$(var.SolutionDir)\Proj.Setup\DepCustomAction.CA.dll"/>
<CustomAction Id="CheckDepType" BinaryKey="DepTypeCustomActionBinary" DllEntry="CustomAction1" Impersonate="no" Execute="deferred" Return="check" HideTarget="no" />
<InstallExecuteSequence>
<Custom Action="CheckDepType" After="InstallFinalize">NOT Installed</Custom>
</InstallExecuteSequence>
Above is my code and I am getting below error:
CheckDepType is a in-script custom action. It must be sequenced in between the InstallInitialize action and the InstallFinalize action in the InstallExecuteSequence table

I'll just add a short answer rather than adding too many comments. I am not sure what dscrt40.dll is doing - is it a file you use during installation for some runtime dependency? I wouldn't recommend installing your own files into a pre-existing folder - if that is what you are doing.
I suppose you could try to use the RemoveFile construct to have the Windows Installer engine remove the file in question on install, this should prevent the need for a custom action. You must not do this if you install the file you are removing via a Windows Installer component first - then self-repair is likely to kick in to put it back afterwards.
A custom action that makes changes to the system can not be sequenced after InstallFinalize - the database change transaction ends with InstallFinalize, and you no longer have elevation for the custom actions that follow after InstallFinalize (immediate mode custom actions can be inserted, but they will fail unless you are running with admin rights - don't try it - it is impossible to rely on). You can only insert change custom actions (deferred custom actions) after InstallInitialize and before InstallFinalize in the InstallExecuteSequence.
You should be aware that files will be present on disk after the action InstallFiles has run (technically on the second run through the InstallExecuteSequence - the first run - immediate - just creates an execution script, the second run - deferred - executes the script), so you can in principle delete files after this action has run, but it doesn't really make sense to do so.
Why do you need to delete this file?
Do you install this file yourself or is it a pre-existing file?

Related

CustomAction run as administrator

I have created a custom action:
<CustomAction Id='AddEventLog' BinaryKey='CustomActionEventLog.dll' DllEntry='AddEventLog' Return="check" Execute="immediate"/>
Install sequence
<Custom Action="AddEventLog" Before="InstallFinalize" />
My installer does pop up and say that it needs admin rights to run. Which I grant it.
InstallPrivileges='elevated' InstallScope='perMachine' AdminImage='yes'
However when it runs the custom action it doesn't work because its not running as administrator.
I even tried adding the following to app.manifest on my custom action project dll. It didn't help.
<requestedExecutionLevel level="requireAdministrator" uiAccess="false" />
I have scoured all the tutorials and forum posts I can find on this subject. Noting has worked yet.
If anyone has any better tags for this please feel free to add them I have been struggling with this all day.
Update for clarification:
While my customAction does work with EventLog I am not using http://schemas.microsoft.com/wix/UtilExtension Util:EventSource. It is a genral question can you even force a customAction to run as administrator?
To run any custom action with administrator privileges you must run the custom action during the Server portion of the installation. ie: it must be a deferred custom action. Otherwise, I think you get a consent.exe message box asking for administrator privileges.
All msi installs work in two parts, Client and Server portions of the install. The Client portion is where you see the UI and set properties that may determine where things get installed and what gets installed (they must be marked Secure for the Server portion of the install to have access to them). The Server portion is what actually puts the files on your system. This always (??) requires administrator privileges because it can be writing stuff into Program Files and other protected file locations.
These custom actions must be marked "Execute='deferred'" and must also be scheduled between the InstallaInitialize and InstallFinalize.
Also to note, if you want to use values of any properties from your installation within the custom action you need to use a separate custom action which sets a specially named property with a special format. You then get the property values in your custom action querying the CustomActionData of the session object. There are lots of examples out there you can find.
Disclaimer, I've not done this previously, and personally I'd take the other approach of using the wix extensions, but you should be able to give elevated permission to your custom actions by using deferred execution and not impersonating the current user. So in your case, Execute="immediate" is what's standing in your way.
<CustomAction Id="MyCustomAction" BinaryKey="WixCA" DllEntry="CAQuietExec" Execute="deferred" Return="check" Impersonate="no"/>
<!-- -or- -->
<CustomAction Id="MyCustomAction" BinaryKey="WixCA" DllEntry="CAQuietExec" Execute="commit" Return="check" Impersonate="no"/>
Source

Strange behaviour of MSI installer on uninstall package

I made something wrong in my installer, but I don't know what it is:
during uninstallation I see how all contents of the product folder is disappearing...
...and then, after uninstallation is complete, the contents is appearing again - my product is not uninstalled actually.
Such behaviour is not always, but happens accidentally (or I didn't catch some factors).
Can anybody help with this issue?
I have checked in the EventViewer that uninstallation completed with error 1603.
The documentation tells that this error means:
A system restart may be required because the file being updated is also currently in use.
But no product's files were opened during uninstallation. Also I stopped all applications from my product.
The reason became simple. In the InstallExecute sequence I had:
<InstallExecuteSequence>
<Custom Action="ModifyServiceConfig" Before="InstallFinalize"/>
</InstallExecuteSequence>
As a result, on uninstallation this custom action was calling too, and I got an error 1603.
I didn't considered the fact that instructions inside InstallExecute sequence are called during uninstallation too.
The fragment above must look like this:
<InstallExecuteSequence>
<Custom Action="ModifyServiceConfig" Before="InstallFinalize">NOT Installed</Custom>
</InstallExecuteSequence>
That means that this custom action must be called only during installation.

Wix error 1721 related to CustomAction

I have following CostomAction
<Binary Id='ManualsBat' SourceFile='bin\Debug\test.bat' />
<CustomAction
Id="manuals"
BinaryKey="ManualsBat"
ExeCommand="[SourceDir]Manuals "[Agent]Manuals""
Execute="immediate"
Return="check" />
test.bat contains the following lines :
#echo off
echo Hello this a test batch file
pause
mkdir %2
copy %1 %2
What it is basically intended to do is, when the installer is run, the batch file needs to get executed. The batch file has to create a new directory "[Agent]Manuals" and it has to copy all the files from [SourceDir]Manuals to [Agent]Manuals.
When I builds .wxs it does not give any error bur when I run the .msi then it complains of the following in the log files
Error 1721. There is a problem with this Windows Installer package. A program required for this install to complete could not be run. Contact your support personnel or package vendor. Action: manuals, location: C:\Windows\Installer\MSI1F50.tmp, command: C:\dev\CD\Agent\pd\components\link\source\Link\Installer\WiX\WiX\bin\Debug\Manuals "D:\Cam\city\Agent\Manuals
Has anyone had experience with this kind of error. It will be great if someone can help me resolve this.
Most likely your custom action needs Administrator privileges. Try setting Execute attribute to deferred and Impersonate to no. Please note that these options require the action to be scheduled after InstallFinalize standard action.
Maybe problem in quotes. Change in ExeCommand quotes.
Try this:
<Binary Id='ManualsBat' SourceFile='bin\Debug\test.bat' />
<CustomAction
Id="manuals"
BinaryKey="ManualsBat"
ExeCommand='"[SourceDir]Manuals" "[Agent]Manuals"'
Execute="deferred"
Impersonate="no"
Return="check" />
<InstallExecuteSequence>
<Custom Action="manuals" Before="InstallFinalize">Not Installed</Custom>
</InstallExecuteSequence>
You generally need to call cmd /c foo.bat ( or command on Win9x ) to process .bat files.
However, I would never, ever do this in one of my installers. It violates the overall design on Windows Installer. MSI is a transactional, declarative programming language. Injecting out of process procedural code greatly increases the likelyhood of failure ( as you are experiencing ) and worse defeats the transactional benefits of MSI.
For example, if you create a folder and copy a file, that won't get undone during a rollback and it won't get removed during an uninstall. Instead, you should be using the built in Windows Installer features ( CreateFolder and CopyFile elements ) to achieve your goals.
On the occasion that custom actions are truely needed (in your example you are merely reinventing the wheel with an inferior solution) they should be designed using robust languages and maintaining a declarative (data driven) and transactional design while respecting the security model that MSI uses.

Deleting files and directories before installation of MSI

Our product was installed via InstallShield Setup over the years. I changed the installation to MSI (WiX) this year. Now the MSI should clean up the directory, which remains the same.
One custom action in the MSI I implemented to start the uninstallation of the old product:
<CustomAction Id="UninstallIS" Property="QtExecCA" Value=""[WindowsFolder]IsUn0407.exe" -f "[ProgramFilesFolder]\company\product\Uninst.isu"" Execute="deferred" />
<CustomAction Id="QtExecCA" BinaryKey="WixCA" DllEntry="CAQuietExec" Execute="deferred" Return="ignore" Impersonate="no" />
After the removal of the old product there are temporary files and some subdirectories that are different from client to client and are unknown to the InstallShield Setup, so I would try to delete them via the MSI.
Keeping the UAC in mind, I think that I can't use command-line commands to do this also the 'Remove File Table' is not useful here (to much unknown files and many directories).
What is a possible way to do this?
Thank You for any help!
You can use a Deferred custom action which has Impersonate flag set to "no". This way it will run under the local system account with full privileges.
The custom action can use custom code (for example an EXE or DLL) or a command line.
Please note that deferred custom actions can be scheduled only after InstallInitialize action in InstallExecuteSequence.
As a side-note, make sure you thoroughly test it. Deleting files from the target machine is very dangerous. You never know what you may end up deleting.

How to execute Custom Action before RemoveExistingProducts with After="InstallValidate" in WiX

I have something like this:
<InstallExecuteSequence>
<RemoveExistingProducts After="InstallValidate"/>
</InstallExecuteSequence>
Since one of the uninstallation fails i need to execute a Custom Action to solve the problem BEFORE RemoveExistingProducts. Something in the lines of:
<CustomAction Id="FixStuff" .. />
<InstallExecuteSequence>
<Custom Action="FixStuff" Before="RemoveExistingProducts" />
<RemoveExistingProducts After="InstallValidate"/>
</InstallExecuteSequence>
This of course doesn't work since Custom Action cannot be before InstallInitialize. I'd really like to remove existing products between InstallValidate and InstallInitialize, but i'd like to execute FixStuff before removing existing products.
Is it even possible to do that?
Unfortunately you cannot run an elevated custom action before RemoveExistingProducts with your current configuration.
Some possible approaches would be:
Move RemoveExistingProducts right before InstallFinalize. This solves the custom action problem, but other problems may occur since this approach has many restrictions (the components need to maintain their names and GUIDs between versions, your custom actions should be aware that the upgrade is performed at installation end etc.).
Create an EXE bootstrapper which fixes the old installer before launching the new MSI. This bootrapper can require Administrator privileges through a manifest:
http://msdn.microsoft.com/en-us/library/bb756929.aspx
Repair the broken MSI by using this method:
fix the problem in the old MSI
create a BAT or EXE bootstrapper which recaches it through this command:
msiexec /fv <path_to_msi>
distribute this MSI as an update before your new package
When your new package runs RemoveExistingProducts, the old cached MSI should be fixed and it should uninstall correctly.