WIX: Non responsive app prevents install/update - wix

We had deployed our Notification area (Tray) app with a fault. It had no top level window and therefore did not receive WM_CLOSE events. In short, if Windows Installer tries to close it with its built in functions during an upgrade or uninstall (it shows a dialog to shut down the app), it will fail closing the app. The tray process is still running in Taskmanager and the exe file is therefore locked.
I would like to have the following:
The setup should kill the running tray application up until a specific file/install version.
Or, if this is not possible prevent installation for old versions and tell the user to manually remove it.
I tried to start Notepad (as test) for old versions before the "please shutdown" dialog appears but did not succeeded.
I tried to start it with Before="ValidateInstall" but it did not run.
I tried to start it with After="ValidateInstall" then notepad opened but ran AFTER the setup detected that the file is running.
Perhaps not all properties are set Before="ValidateInstall"?
Perhaps my Custom Actions are somehow autmatically deferred?
Some code snippets:
<Product Id="*"
Codepage="65001"
Language="!(loc.LANGUAGE)"
Manufacturer="$(var.AppManufacturer)"
Name="$(var.AppCode), $(var.AppVersion)"
UpgradeCode="$(var.AppUpgradeCode)"
Version="$(var.AppVersion)">
<Package Comments="$(var.AppCode),
$(var.AppVersion)"
Compressed="yes"
InstallPrivileges="limited"
InstallScope="perUser"
InstallerVersion="301"
Languages="!(loc.LANGUAGE)"
Manufacturer="$(var.AppManufacturer)"
Platform="x86"
SummaryCodepage="1252"/>
<Property Id="PROP_APP_IGNORES_SHUTDOWN">
<DirectorySearch Id="DirSrch_PIAS_Version" Path="[DIR_ID_USERPROGRAMFOLDER]">
<FileSearch Name="$(var.MyExe.TargetFileName)"
MaxVersion="6.1.3432.99999"/>
</DirectorySearch>
</Property>
<Property Id="QtExecCmdLine"
Value='"$(var.SysSystem32)\taskkill.exe" /F /IM $(var.MyExe.TargetFileName)'/>
<CustomAction Id="CA_KillApp"
BinaryKey="WixCA"
DllEntry="CAQuietExec"
Execute="immediate"
Impersonate="yes"
Return="ignore" />
<Property Id='NOTEPAD'>$(var.SysWindir)\Notepad.exe</Property>
<CustomAction Id="CA_OpenNotepad"
Property="NOTEPAD"
ExeCommand=""
Return="asyncNoWait" />
<MajorUpgrade Schedule="afterInstallValidate"
DowngradeErrorMessage="[VSDVERSIONMSG]"
AllowDowngrades="no"
AllowSameVersionUpgrades="yes" />
<InstallExecuteSequence>
<Custom Action="CA_OpenNotepad" Before="CA_KillApp">PROP_APP_IGNORES_SHUTDOWN</Custom>
<Custom Action="CA_KillApp" Before="InstallValidate">PROP_APP_IGNORES_SHUTDOWN</Custom>
</InstallExecuteSequence>
</Product>

Related

Installing TopShelf with WiX fails due to Admin Rights

So I am trying to install an application built using TopShelf, the application itself runs well and has no problems. The problem I run into is when I try to install the service. The TopShelf service is installed (from an administrator command line) using the myapp.exe install <options> instruction. I have wrapped the instruction in a custom action (see below). This runs, in that I can see a black box pop-up on install. The service fails to install, however. When I run the msi install from an administrator command line, the service installs correctly. I have included all Administrator related parameters in the WiX file (see below also). I am completely out of ideas and in need of help, can anyone see anything in the WiX files or does anyone have any idea what is preventing the service from installing?
What I have tried:
Topshelf - Custom Action in Wix Not Executing
Add Coffee and Shake Well - TopShelf
I have also tried wrapping the call to the topshelf app in a separate WiX custom Action project to execute and this also fails for the same reason.
<Product Id="*" Name="PackageName"
Language="1033"
Version="1.0.0.0"
Manufacturer="Manufacturer"
UpgradeCode="e7780903-3cf9-4ecc-b65a-45bc18b500df">
<Package InstallerVersion="200"
Compressed="yes"
InstallScope="perMachine"
InstallPrivileges="elevated"
Platform="x64" />
<Property Id="MSIUSEREALADMINDETECTION" Value="1" />
<MajorUpgrade AllowSameVersionUpgrades="yes"
DowngradeErrorMessage="A newer version of [ProductName] is already installed."
Schedule="afterInstallInitialize" />
<MediaTemplate EmbedCab="yes"/>
<Feature Id="ProductFeature" Title="FeatureName" Level="1">
<ComponentGroupRef Id="ProductComponents" />
</Feature>
<CustomAction Id="InstallService"
FileKey="MyApp.exe"
ExeCommand="install"
Impersonate="yes"
Execute="immediate" />
<CustomAction Id="StopService"
FileKey="MyApp.exe"
ExeCommand="stop"
Execute="immediate" />
<CustomAction Id="UninstallService"
FileKey="MyApp.exe"
ExeCommand="uninstall"
Execute="immediate" />
<InstallExecuteSequence>
<Custom Action="InstallService" After="InstallFinalize" >
NOT Installed AND NOT REMOVE
</Custom>
<Custom Action="StopService" After="InstallInitialize" >
(NOT UPGRADINGPRODUCTCODE) AND (REMOVE="ALL")
</Custom>
<Custom Action="UninstallService" After="StopService">
(NOT UPGRADINGPRODUCTCODE) AND (REMOVE="ALL")
</Custom>
</InstallExecuteSequence>
</Product>
There are a couple of problems with your custom actions. One is that the InstallService CA is immediate which means 1) It's before the files are installed and 2) it won't run with elevation. It needs to be deferred and before InstallFinalize.
If this is just an ordinary Windows service, then you should use a ServiceInstall node to install it (and uninstall it) as well as ServiceControl to stop, start, and delete it.
I solved this problem using the following code
<CustomAction Id="InstallService" FileKey="MyApp.exe" ExeCommand="install start" Impersonate="no" Execute="deferred" />
<CustomAction Id="UninstallService" FileKey="MyApp.exe" ExeCommand="stop uninstall" Impersonate="no" Execute="deferred" />
<InstallExecuteSequence>
<Custom Action="InstallService" Before="InstallFinalize">
NOT Installed AND NOT REMOVE
</Custom>
<Custom Action="UninstallService" Before="RemoveFiles">
(NOT UPGRADINGPRODUCTCODE) AND (REMOVE="ALL")
</Custom>
</InstallExecuteSequence>

Can you launch a non-elevated application from a perMachine WiX package?

We have a per-machine install package built with WiX 3.9.
<Package InstallerVersion="405" Compressed="yes" InstallScope="perMachine" />
And we are also using WixShellExec to launch an application from a CustomAction as part of the package install.
<Property Id="WixShellExecTarget" Value="[#Application.exe]" />
<CustomAction Id="LaunchApplication" BinaryKey="WixCA" DllEntry="WixShellExec" Impersonate="yes" />
<InstallExecuteSequence>
<Custom Action="LaunchApplication" After="InstallFinalize">NOT Installed</Custom>
</InstallExecuteSequence>
This launches our application as expected, but it launches the application with elevated permissions.
From what we have seen, it is not possible to launch the application without elevated permissions from a per-machine install package. We have tried various combinations of Impersonate="yes|no" and Execute="deferred|immediate". We have also tried using a FileKey custom action directly to launch the application.
We are using a custom bootstrapper application and so cannot use the built-in WiX UI around this functionality. Is the only way to achieve a non-elevated launch of our application to do so manually from our custom bootstrapper application?
You could try this - it's from a reliable source:
http://blogs.msdn.com/b/oldnewthing/archive/2013/11/18/10468726.aspx

Elevated custom action before removing files

I'm trying to write an Installer for my Windows Service using WiX. My executable can register/unregister itself as a Windows Service using the command line parameters --install and --uninstall. This is what I came up with:
<CustomAction Id='InstallAsService' FileKey='CCWirelessServer.exe' ExeCommand='--install' Return='check' Impersonate='no' Execute='deferred' />
<CustomAction Id='InstallAsServiceRollback' FileKey='CCWirelessServer.exe' ExeCommand='--uninstall' Return='check' Impersonate='no' Execute='rollback' />
<CustomAction Id='UninstallAsService' FileKey='CCWirelessServer.exe' ExeCommand='--uninstall' Return='check' Impersonate='no' Execute='deferred' />
<InstallExecuteSequence>
<Custom Action='InstallAsService' After='InstallFiles' >NOT Installed</Custom>
<Custom Action='InstallAsServiceRollback' Before='InstallAsService' >NOT Installed</Custom>
<Custom Action='UninstallAsService' Before='RemoveFiles' >Installed</Custom>
</InstallExecuteSequence>
Both install and uninstall basically work. But during uninstall I get the following message:
The setup must update files or services that cannot be updated while the system is running. If you choose to continue, a reboot will be required to complete the setup.
Despite this error message, the service gets unregistered and the files are deleted without a reboot. To me this looks like the installer is checking if CCWirelessServer.exe is opened before it executes my custom action.
So my question is: How do I need to modify my install execute sequence so that this error message does no longer appear?
If you are developing for Windows Installer > 3.1 you can take a look at the MSIRESTARTMANAGERCONTROL-property to see if it it set properly or if other values would would stop displaying the message.
I could suppress the message using the following values:
<Property Id="MSIRESTARTMANAGERCONTROL" Value="Disable" Secure="yes" />

Wix: how to forcefully kill a process/task?

I need to forcefully kill a process that is running in the background before attempting to delete any files, when running an Uninstall from an MSI created with Wix. The main application consist of a trayicon which reflects the status of the bg-process monitoring local windows services (made on C#, though this may not be so relevant going further).
I first tried the following:
<File Id='FooEXE' Name='Foo.exe' Source='..\Source\bin\Release\Foo.exe' Vital='yes' />
...
<InstallExecuteSequence>
<Custom Action="CloseTray" Before="InstallValidate" />
</InstallExecuteSequence>
...
<CustomAction Id="CloseTray" ExeCommand="-exit" FileKey="FooEXE" Execute="immediate" Return="asyncWait" />
The tray icon is immediately closed after confirming application-close dialog, but the Foo.Exe task still appears on the taskmgr after the uninstall completed. Also,the following error message was given:
Thats why, then I tried this:
<InstallExecuteSequence>
<Custom Action="Foo.TaskKill" Before="InstallValidate" />
</InstallExecuteSequence>
...
<CustomAction Id="Foo.TaskKill" Impersonate="yes" Return="asyncWait" Directory="WinDir" ExeCommand="\System32\taskkill.exe /F /IM Foo.exe /T" />
After obtaining the same result, tried:
<Property Id="QtExecCmdLine" Value='"[WinDir]\System32\taskkill.exe" /F /IM Foo.exe'/>
...
<InstallExecuteSequence>
<Custom Action="MyProcess.TaskKill" Before="InstallValidate" />
</InstallExecuteSequence>
...
<CustomAction Id="MyProcess.TaskKill" BinaryKey="WixCA" DllEntry="CAQuietExec" Execute="immediate" Return="ignore"/>
Sample which I took from here: How to kill a process from WiX
lately when all else failed, I also tried this without any success:
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi" xmlns:util="http://schemas.microsoft.com/wix/UtilExtension">
...
<InstallExecuteSequence>
<Custom Action="WixCloseApplications" Before="InstallValidate" />
</InstallExecuteSequence>
...
<util:CloseApplication Id="CloseFoo" CloseMessage="yes" Description="Foo is still running!" ElevatedCloseMessage="yes" RebootPrompt="yes" Target="Foo.exe" />
This one gave me a different error:
I'm thinking on building a statue in honor to this process that just refuses to die!!! ... either that or think a problem on the application side exists, where I should add something like Application.Exit(); or Environment.Exit(0); at some line inside Program.cs.
Is there any other thing I could do at either Wix or my application to attempt closing it successfully at Uninstall?
Thanks!
Personally I think the best option for you to go with is the in-built CloseApplication method rather than your previous options.
The error you are getting for that (Error code 2762) is because you are trying to schedule the action in the immediate sequence but have the ElevatedCloseMessage="yes" set which triggers it as a deferred action. Either remove this attribute or schedule it in the deferred sequence.

Uninstallation problem

When program is installed it is fired(by the installer) right after installation finishes. But when i uninstall the program from Control Panel, then it tries to open the exe too, which gives the following error:
Windows cannot find 'MyExe.com'. Make sure you typed the name correctly, and then try again. To search for a file, click the Start button, and then click Search.
with the cmd.exe in the background.
after i press OK, another window pops up, saying:
There is a problem with this Windows Installer package. A program run as part of the setup did not finish as expected. Contact your support...
Although the program gets uninstalled, these errors are not desirable.
Also when i install newer version and older version of the program already exists, i get similar messages as the installer tries to uninstall older version first.
Here is the code:
....
<Property Id="PREVIOUSVERSIONSINSTALLED" Secure="yes" />
<Upgrade Id="D2B0D435-0F86-4D5E-A988-B24215882***">
<UpgradeVersion
Minimum="1.0.0.0" Maximum="99.0.0.0"
Property="PREVIOUSVERSIONSINSTALLED"
IncludeMinimum="yes" IncludeMaximum="no" />
</Upgrade>
<CustomAction Id="LaunchApp" Directory="INSTALLDIR" ExeCommand="[SystemFolder]cmd.exe /C start MyExe.exe" />
<InstallExecuteSequence>
<RemoveExistingProducts Before="InstallInitialize" />
<Custom Action="LaunchApp" After="InstallFinalize" />
</InstallExecuteSequence>
</Product>
</Wix>
What i would like, is that installer would try to run the program only when installation occurs and do nothing when uninstallation is processed.
Thanks in advance!
Your problem is that you don't have a condition on the action so it fires every time. At a minimum you need a condition of "Not Installed". However for a more elegant solution, read:
How To: Run the Installed Application After Setup