I have an .exe embedded inside my MSI installer which I'd like to somehow call directly from the installer, before the the 'InstallFiles' action occurs.
It's defined as follows:
<CustomAction Id="LaunchInstallManager_TryUninstall" Return="ignore" Directory="INSTALLFOLDER" Execute="deferred" Impersonate="no" ExeCommand=""[#fil713F8F6A7BC9B98857D779B9B29873E1]" /someargument"></CustomAction>
<Custom Action="LaunchInstallManager_TryUninstall" Before="InstallFiles">NOT Installed</Custom>
But upon looking at the logs, it looks like it's (trying to be) called from the install destination.
Is such a thing possible?
It is possible, but in a different way. The 'run EXE' type of custom action will always search for the executable on the target system. Thus, if your executable is installed along with your app, it is not an option.
Here is another way:
First, author your EXE as a <Binary> instead.
It is as easy as <Binary Id="MyEXE" SourceFile="PATH\TO\EXE" />.
Add a DLL deferred custom action, which will extract the binary, run it with parameters and clean up afterwards.
This post can give you an idea how to extract the binary using C# and DTF. Besides, in case you need to pass parameters, make sure you do it the right way for deferred custom action.
Finally, remember that each deferred custom action (that is the one to change the target system) must have corresponding rollback action. This article might give you some hints on how to test the direct and rollback behaviors of your custom actions.
Related
In the process of converting from installshield to wix, I am porting over the custom actions.
One is for determining previously installed versions and popping up a message if any are found. I guess the guids weren't properly tracked before.
Within installshield, it appears they had the CA scheduled after ValidateProductID. I tried to do the same:
<CustomAction Id="CA_CheckPreviousVersions.SetProperty" Property="CA_CheckPreviousVersions" Value="ERROR_UNINSTALL_VERSION=$(var.ERROR_UNINSTALL_VERSION)" />
<CustomAction Id="CA_CheckPreviousVersions" DllEntry="CheckPreviousVersions" Execute="deferred" BinaryKey="LunaClientCustomActions_dll" />
<InstallExecuteSequence>
...
<Custom Action="CA_CheckPreviousVersions.SetProperty" After="ValidateProductID" />
<Custom Action="CA_CheckPreviousVersions" After="CA_CheckPreviousVersions.SetProperty" >NOT Installed AND NOT PATCH</Custom>
</InstallExecuteSequence>
Except, I get a nasty warning:
error LGHT0204: ICE77: CA_CheckPreviousVersions is a in-script custom action. It must be sequenced in between the InstallInitialize action and the InstallFinalize action in the InstallExecuteSequence table
Why am I getting this, whereas IS seemingly permitted it? More to the point, how do I replicate the behaviour that was previously in place?
You haven't shown the custom action definition, but the message indicates it's deferred and must be sequenced as the message indicates. Perhaps the original type was immediate.
If you mean previously installed versions of your product (or in fact any MSI-based product for which you know the UpgradeCode) there is no need for any code. If you were to use a WiX MajorUpgrade element you can detect previous versions because the WIX_UPGRADE_DETECTED property will be set, and you could use that as a launch condition, or whatever it is you plan to do. Or use Upgrade and UpgradeVersion elements to detect previous versions and version ranges. From what you've said there seems no need to run code. Just use the upgrade search properties and show dialogs or errors or whatever.
I've used the dark.exe to create a WXS file from my 'old' Visual Studio 2010 msi file.
When I open the created WXS file, It has binary references on the top of the file that I can't explain. Can somebody tell me about it? And where can I find some documentation about it?
<Binary Id="InstallUtil" SourceFile="C:\Temp\Binary\InstallUtil" />
<Binary Id="MSVBDPCADLL" SourceFile="C:\Temp\Binary\MSVBDPCADLL" />
<Binary Id="VSDNETCFG" SourceFile="C:\Temp\Binary\VSDNETCFG" />
<Binary Id="DefBannerBitmap" SourceFile="C:\Temp\Binary\DefBannerBitmap" />
<Binary Id="UpFldrBtn" SourceFile="C:\Temp\Binary\UpFldrBtn" />
<Binary Id="NewFldrBtn" SourceFile="C:\Temp\Binary\NewFldrBtn" />
The top three are giving me the most questions because I don't where there for and what they do.
Short answer - these files are used in ui dialogs, custom actions, all places where some files are applicable to the functionality of the setup itself, but the product it installs.
In your case, the first three are DLLs used by Visual Studio Setup Projects to perform custom actions - MSI extensibility blocks. The last three are the icons used in UI dialogs later in code.
To get the files themselves, you should use export binaries parameter for Dark.exe.
Now, your options here depend on what you want to achieve. If your task is just upgrade your setup to VS2012, quick and dirty, then use the exported files as they were, it should work.
If, however, you want to do it clean and nice, or you should update your setup with new features, then you will have to rewrite these.
For UI: if your project does not contain custom UI, I suggest switching to WIX UI library - nice and built-in. If you have custom UI, you may extend it, but it is a lot more work. There are visual UI editors for WIX.
For custom actions: custom action is something you use when MSI/WIX abilities do not give you enough. To upgrade these, you should look where these first three binaries are used, and how they are called. Usually, the meaning of custom action may be devised from its name. Then, you have to replace these custom actions with your own (or ready-made by others or WIX team) that do the same. Then you may remove the unused binaries.
How to sequence a custom action to execute only when installation is interrupted or completed with error?
Is there any windows installer property which returns current installation status (failed/succeed)?
The OnExit attribute of the <Custom> element is what you're looking for. It is mutually exclusive with Before, After, and Sequence attributes and can have the following values: success, cancel, error, suspend.
UPDATE: basically, this is what I mean:
1) Define a custom action which will do the work you'd like it to do (gather some failure data). Note that you'll have to define N custom actions pointing to the same target because the CustomAction MSI table expects Id as a primary key (let's assume it's DLL CA):
<CustomAction Id="LogFailureOnCancel" BinaryKey="CustomActions" DllEntry="LogFailure" ... />
<CustomAction Id="LogFailureOnError" BinaryKey="CustomActions" DllEntry="LogFailure" ... />
NOTE: both definitions point to the same real action (DllEntry attribute).
2) Schedule these custom actions appropriately:
<Custom Action="LogFailureOnCancel" OnExit="cancel" />
<Custom Action="LogFailureOnError" OnExit="error" />
To the extent that Windows Installer allows it, this is only possible during custom actions scheduled for rollback. However rollback only applies to the deferred script, so it's only available for actions scheduled between InstallInitialize and InstallFinalize. If an immediate-mode action outside this scheduling window causes the installation to abort, rollback does not apply.
Assuming you're using a C++ or InstallScript action, you can find out if rollback is enabled, and if you're in rollback, with calls to MsiGetMode - using MSIRUNMODE_ROLLBACKENABLED or MSIRUNMODE_ROLLBACK respectively.
I want perform custom action after files are copy in destination folder.
In custom action i run copied script file so give me error file not found.
<CustomAction Id="RunDBScript"
BinaryKey="CA"
DllEntry="RunDBScript"
Execute=" immediate"
Return="check" />
<Custom Action="RunDBScript" After="InstallFiles">
<![CDATA[NOT Installed]]>
</Custom>
this custom action give an error file/directory not found. so this action call before file copy.
so, how to call custom action after file copy?
I am not understand why this custom action call before InstallFiles even though i am specified After="InstallFiles".
Move your custom action after InstallFinalize. This is the only place in InstallExecuteSequence where Immediate actions can be executed after installing the product files.
When you use deferred custom actions, you must access values through session.CustomActionData["propertyname"].
Session dictionary values can be read only by immediate custom actions, where the execution script is being written.
The deferred custom actions are executed at script running time, so the project properties are no longer available.
To make use of it, you must implement a double custom action in order to provide the desired properties for the real custom action.
Follow the bellow example:
<CustomAction Id="CustomActionID_Data" Property="CustomActionID" Value="INSTALLDIR=[INSTALLDIR];OTHERPROPERTY=[OTHERPRPJECTPROPERTY]"></CustomAction>
<CustomAction Id="CustomActionID" BinaryKey="FILEBINARYID" DllEntry="METHODNAMEATCUSTOMACTION" Execute="deferred"></CustomAction>
At this example, you need to call at InstallExecutionSequence the custom action "_Data" and after call the real one, so the first "_Data" will se the desired properties. Then you can access those properties on your code using session.CustomActionData[""].
Just complementing, bellow is an example of how to call the custom actions at InstallExecuteSequence.
<Custom Action="CustomActionID_Data" After="InstallFiles">NOT (REMOVE="ALL")</Custom>
<Custom Action="CustomActionID" After="CustomActionID_Data">NOT (REMOVE="ALL")</Custom>
I have the following CustomAction in my project:
<CustomAction Id="InstallDriver"
Return="check"
Execute="deferred"
Impersonate="no"
FileKey="FileDriverInst"
ExeCommand="-install" />
<InstallExecuteSequence>
<Custom Action="InstallDriver" Before="InstallServices" />
</InstallExecuteSequence>
The program that installs the driver produces useful return codes, for example if the installation failed because the system needs to be restarted following a previous driver uninstall.
Currently if anything other than success is returned, I get a dialog saying 'A program run as part of the setup did not finish as expected.' and the installation fails. This is not optimal.
How can I get and handle return codes?
Windows Installer doesn't support handling custom action return values.
For an EXE custom action a non-zero return value is interpreted as an error and the installation stops. Only a win32 DLL or VBScript custom action can change the installation behavior through its return code, but it's still very limited.
If you want to reboot the machine after install, you can set the REBOOT property.
Added as an "answer" by request:
Your whole design is not optimal. It's out of process to Windows Installer and isn't declarative. There are better patterns for installing drivers.
That's simply the way MSI handles EXE calls. You'd have to write your own custom actions to wrap the EXE call and then interpret the failure reason. To me this just adds yet another failure point.
You can't get a return code from a CustomAction, but in a round about way you can set what that return code would be on a property. That might as well be the same thing as getting the return code.
You have to get it within the script/dll your custom action is performing. Otherwise, the return code only shows up in the log.
For example, if you have property like
<Property="MyCode" Secure="yes">
Then within VBScript (or Jscript) you can get the value of that property like this:
VBScript
Session.Property("MyCode")
Initially, it is null. You can set it in VBScript like this:
If someCondition = 4 Then
Session.Property("MyCode") = "4" // For a return code of 4
End If
Once back in your WiX .wxs file, if you look at the value of your property, it is now 4. You could even use it in CDATA tags.
For example, only spawn a dialog if MyCode is equal to 4.
<Publish Dialog="SpawnDialog" ...><![CDATA[ MyCode = 4 ]]></Publish>