wix - session.message is not showing at time of installation - installation

Wix CustomAction [C#] session.Message(Messagebox) is not displayed during installation.
I have a Session.Message added in my custom action,
public static ActionResult DisplayConfirmationMessage(Session session) {
Record record = new Record();
record.FormatString = pMessage;
Session.Message(InstallMessage.Error
| (InstallMessage)System.Windows.Forms.MessageBoxIcon.Warning
| (InstallMessage)System.Windows.Forms.MessageBoxButtons.OK, record);
}
And in wxs file custom action
<CustomAction Id="RestartAction" BinaryKey="CustomActions" DllEntry="DisplayMessage" Execute="immediate" Return="check" />
and in install execute (only one custom action call):
<InstallExecute>
<Custom Action="RestartAction" After="InstallFinalize"></Custom>
</InstallExecute>
the message box is displayed only at time of uninstall. But during installation it is getting logged to session.Log.
I have checked with 'NOT Installed AND NOT REMOVE' still same results.
I am blocked on this, please help.
Thank you in advance.

Related

Rename Existing Folder using Wix

Our applications installs in a offline network that we generally don't have access to. It is also a high-availability application. We need our old application folder to still be available for use by our user, so we would like to rename the current application folder before installing the new one. That way, if we have some bugs that are no-go, we need them to be able to quickly revert to the old program.
Is this possible with Wix?
Also, we know it's not ideal, but it's what we have, so please just answer the question instead of saying "don't do that".
Just create Custom action that will start before CostFinalize and move your folder.
For example:
<InstallExecuteSequence>
<Custom Action="RenameFolder"
Before="CostFinalize"/>
</InstallExecuteSequence>
<CustomAction Id="RenameFolderCustomAction" BinaryKey="YourCustomActionDll" DllEntry="RenameFolderMethod" Execute="immediate" Impersonate="no" Return="check" />
And Your custom action will look like:
[CustomAction]
public static ActionResult RenameFolderMethod(Session session)
{
session.Log("Begin RenameFolderMethod");
Directory.Move(source, destination);
return ActionResult.Success;
}
Also, you'll need to add custom action that will copy it back in case of error or cancel. For this purpose you can use OnExit custom action.
<InstallExecuteSequence>
<Custom Action="RenameFolder" Before="CostFinalize"/>
<Custom Action="InstallationFailed" OnExit="cancel" />
<Custom Action="InstallationFailed" OnExit="error" />
</InstallExecuteSequence>
<CustomAction Id="InstallationFailed" BinaryKey="YourCustomActionDll" DllEntry="InstallationFailedMethod" Execute="immediate" Impersonate="no" Return="check" />
And action will be the same, just with reversed parameters:
[CustomAction]
public static ActionResult InstallationFailedMethod(Session session)
{
session.Log("Begin InstallationFailedMethod");
Directory.Move(destination, source);//move it back
return ActionResult.Success;
}
Also you can use properties to store source and destination paths. And you can even define them while running your msi if needed.
How to add custom actions in general

Executing a CustomAction in Wix with 'if exist'

Hi I would like to perform the following CustomAction when installing my program:
<!--Include the custom action for overwrite Client.config-->
<CustomAction Id="SetCmdLineParams" Property="QtExecCA" Value='if exist "[CURRENTDIRECTORY]\Client.config" ("xcopy" /Y "[CURRENTDIRECTORY]\Client.config" "[INSTALLFOLDER]")' Execute="immediate" />
<CustomAction Id="QtExecCA" BinaryKey="WixCA" DllEntry="CAQuietExec" Execute="deferred" Return="check" Impersonate="no"/>
<!--Include the InstallExecuteSequence for overwrite Client.config-->
<InstallExecuteSequence>
<Custom Action="SetCmdLineParams" After="CostFinalize"/>
<Custom Action="QtExecCA" Before="InstallFinalize" />
</InstallExecuteSequence>
Unfortunately this doesn't work because: CAQuietExec: Command string must begin with quoted application name.
But if I quote "if exist", then the command does not work. What can I do now?
if exist is a feature of cmd.exe. You'd need to say cmd /c first or create a .bat file and call that.
Honestly though, this is really fragile code. For one CURRENTDIR isn't always going to be what you think it is. You should write a C++ or C# custom action that uses the OriginalDatabase property to get where the MSI is running from and copy the config file from there.
Another approach I've used very successfully in the past is to write a utility that can transform a seed MSI by embedding a user provided config file into it. Now the deployment story is simplified.

Custom Action After InstallInitialize to check the Drive Existence

I have written a custom action in C# to check for the drive existence like below, I got stuck in between.
[CustomAction]
public static ActionResult MySimpleAction(Session session)
{
if (Directory.Exists("F:\\"))
{
return ActionResult.Success;
}
else
{
return ActionResult.Failure;
}
}
And in wxs file, I am running the custom action as like below.
<Binary Id="myAction" SourceFile="MyCustomAction.CA.dll" />
<CustomAction Id="myActionId"
BinaryKey="myAction"
DllEntry="MySimpleAction"
Execute="immediate"
Return="check" />
<InstallExecuteSequence>
<Custom Action="myActionId" After="InstallInitialize" > </Custom>
</InstallExecuteSequence>
If I run the msi in the target machine where I have F:\ drive then installation succeeds, if the target machine doesn't have F:\ drive then Setup failed, I am getting error as "Setup wizard ended prematurely because of an error. Your system has not been modified."
What I am trying to do here is, if F:\ drive is available in the target computer (My Custom action succeeds), I want to set my root drive as F:\, and I want to install the application in F:\MyApp\Bin
<Property Id="ROOTDRIVE"><![CDATA[F:\]]></Property>
<Directory Id="TARGETDIR" Name="SourceDir">
<Directory Id="INSTALLFOLDERLOCATION" Name="MyApp">
<Directory Id="INSTALLLOCATION" Name="Bin">
if F:\ drive is not available in the target computer (My Custom action fails), I want to set my root drive as C:\, and I want to install in C:\MyApp\Bin
<Property Id="ROOTDRIVE"><![CDATA[C:\]]></Property>
<Directory Id="TARGETDIR" Name="SourceDir">
<Directory Id="INSTALLFOLDERLOCATION" Name="MyApp">
<Directory Id="INSTALLLOCATION" Name="Bin">
How can I set the root drive property by using this custom action?
Thanks for the help!
When using an immediate Custom Action, you can set property values by using session["PROPERTYNAME"] so in your case you could use session["ROOTDRIVE"] = "F:\\"; in your Custom Action.
The reason it's failing at the moment is that you are returning a Failure message from your custom action, and since you have specified Return="check", the installer checks the return value, and fails the install if the Custom Action has failed.
You are on the right track. Here's what I do differently.
1) I use the DriveInfo class to see if the drive exists and it's of DriveType Fixed. (Not CDROM, USB Drive, Network....)
2) The custom action is scheduled in both the UI and Execute sequence after AppSearch and sets a property called something like InstallDirOverride. The custom action always returns ActionResult.Success.
3) I use a Set Property custom action (wxs element) to assign InstallDirOverride to INSTALLLOCATION (or INSTALLDIR... whatever you have called your main directory ) with the condition that INSTALLLOCATION doesn't yet have a value and InstallDirOverride does have a value and Not Installed. This custom action gets scheduled in both the UI Sequence and ExecuteSequence prior to CostInitialize.
The result of all this is an installer that defaults to C:\Program Files\My Company\My Product but changes it's behavior to default to something else based on the business rules in your C# custom action. This gives you the flexibility to default the way you want for a specific platform environment and yet still be complaint to Windows Standards when your platform is missing that resource.
I thank Christopher Painter and ChrisPatrick for helping me!!! the below code made the trick to work.
[CustomAction]
public static ActionResult MySimpleAction(Session session)
{
session.Log("DriveInfo Starts");
DriveInfo[] drives = DriveInfo.GetDrives();
foreach (DriveInfo d in drives)
{
if (d.Name.Contains("F") & d.IsReady == true & d.DriveType.ToString() == "Fixed")
{
session["TARGETDIR"] = "F:\\";
}
else
{
session["TARGETDIR"] = "C:\\";
session.Log("No F:\\ Drive Found!!!!");
}
}
session.Log("DriveInfo Ends");
return ActionResult.Success;
And in the .wxs file,
<Binary Id="myAction" SourceFile="MyCustomAction.CA.dll" />
<Directory Id="TARGETDIR" Name="SourceDir">
<Directory Id="INSTALLFOLDERLOCATION" Name="MyApp">
<Directory Id="INSTALLLOCATION" Name="Bin">
<CustomAction Id="myActionId" BinaryKey="myAction" DllEntry="MySimpleAction" Execute="immediate" Return="check" />
<InstallUISequence>
<Custom Action="myActionId" Before="CostFinalize" > NOT Installed </Custom>
</InstallUISequence>

How do I make a WiX installer force VS to install templates?

I've got a WiX installer that is meant to update VS 2010 templates after installing them. The code I'm using is as follows:
<CustomAction
Id="InstallTemplates"
ExeCommand=""[VISUALSTUDIODIR]devenv.exe" /installvstemplates"
Directory="VISUALSTUDIODIR"
Execute="commit"
Return="check"
HideTarget="no"
Impersonate="no"/>
<InstallExecuteSequence>
<Custom Action="InstallTemplates" Before="InstallFinalize"></Custom>
</InstallExecuteSequence>
In the above, VISUALSTUDIODIR refers to the correct location, and templates are correctly deployed. However, it seems that the command does not get called, so no templates are actually installed. What am I doing wrong?
WiX has built-in functionality to do that. Add a reference to WixVSExtension.dll and add the following authoring:
<CustomActionRef Id="VS2010InstallVSTemplates" />
Make sure that VISUALSTUDIODIR is an actual directory in your MSI package (it's saved in Directory table). This is a requirement for this type of custom action.
Also, try creating an installation log and search for your custom action to see what happens.

How to execute custom action only in install (not uninstall)

I'm sure this is fairly easy, but I've kind of had a hard time with it. I've got a custom action that executes a different (non-msi) installer on installation. Unfortunately, I've noticed that it also executes the installer on UNinstallation!
I've looked through the options but I cant' seem to find out how to stop this. If anybody could help me I would be incredibly grateful.
Also, how do I set a custom action to go off only during UNinstall? Any help is greatly appreciated guys!
Add a condition on the action so it's only triggered during installation, not uninstallation.
Action run only during Install
NOT Installed AND NOT PATCH
Action runs during Install and repair
NOT REMOVE
Run on initial installation only:
NOT Installed
Run on initial install or when repair is selected.
NOT Installed OR MaintenanceMode="Modify"
To only run an action during uninstall use the following condition:
REMOVE~="ALL"
To only run an action during upgrade:
Installed AND NOT REMOVE
An example:
<InstallExecuteSequence>
..
<Custom Action="QtExecIdOfCA" Before="InstallFinalize">NOT Installed</Custom>
..
</InstallExecuteSequence>
..
..
<CustomAction Id="QtExecIdOfCA" BinaryKey="WixCA" DllEntry="CAQuietExec" Execute="deferred" Return="ignore" Impersonate="no"/>
Notice! Condition is added to the <Custom> tag and not the <CustomAction> it confused me, because Custom is followed by Action attribue
A bit of a correction:
Finally, to only run an action during uninstall use the following condition:
REMOVE="ALL"
This seems more appropriate as the property REMOVE contains the features being uninstalled.
So if I do a modify to remove one feature, REMOVE is true and the action that was to execute only on uninstall executes on modify.
More details here on MSDN
Please be careful with REMOVE=ALL. It is not available before installvalidate sequence.
And check below links for more details:
http://msdn.microsoft.com/en-us/library/aa371194(v=vs.85).aspx
http://msdn.microsoft.com/en-us/library/aa368013(v=vs.85).aspx
A condition on the custom action, probably with a matching custom action to do the uninstall. Not sure what tools you're using, but assuming the secondary install is tied to a component, I would use that component state. A state of =3 means a target state of installed. A state = 2 means a target state of absent. Note that the state won't be set if there is no change.

Resources