Using WixSharp to build installer,
Is LaunchCondition shown when running in silent mode? (e.g "msiexec /i /qn /quiet")
MSI GUI: MSI has many UILevels - degrees of visible GUI (more on this here). When a setup is run in silent mode, any errors from Launch Conditions will show up in the MSI log instead of a dialog.
This makes sense since you must avoid dialogs showing up when there might be nobody to dismiss them (for example in automatic package deployment systems).
Essentially you can run with basic GUI /qb or reduced GUI /qr or completely silently /qn. When you run silently no dialogs should be shown, and you should consult the log file for results:
Silent MSI installation:
msiexec /i MySetup.msi /qn /L test.log
Test Project: https://github.com/glytzhkof/WiXLaunchConditionTest (MYVALUE is defined in the Property table - change it there to 0 or 1).
Here is a sample log output:
=== Logging started: 28.10.2021 13:07:12 ===
Action start 13:07:12: INSTALL.
Action start 13:07:12: FindRelatedProducts.
Action ended 13:07:12: FindRelatedProducts. Return value 1.
Action start 13:07:12: LaunchConditions.
MSI (s) (F4:DC) [13:07:12:491]: Product: WiXLaunchConditionTest -- Value for MYFLAG must be 1 (true) or 0 (false)
Value for MYFLAG must be 1 (true) or 0 (false)
Action ended 13:07:12: LaunchConditions. Return value 3.
Action ended 13:07:12: INSTALL. Return value 3.
MSI (s) (F4:DC) [13:07:12:493]: Product: WiXLaunchConditionTest -- Installation failed.
MSI (s) (F4:DC) [13:07:12:493]: Windows Installer installerte produktet. Produktnavn: WiXLaunchConditionTest. Produktversjon: 1.0.0.0. Produktspråk: 1033. Produsent: -. Installasjonens resultatstatus: 1603.
=== Logging stopped: 28.10.2021 13:07:12 ===
Admin Rights: It should be noted that an MSI should be run from a cmd.exe with admin rights - or you get no message from the silent installer that the setup failed because of lacking admin rights (the failure is from lacking admin rights, not because of the launch conditions).
This registry script adds context menus in Windows Explorer which can open a cmd.exe in any folder with or without admin rights: https://github.com/glytzhkof/all/blob/master/HKCU_Run-CMD-Shell-Extension.reg. Just merge the registry file and then right click an empty space inside Windows Explorer in any folder. See the commands towards the bottom of the dialog:
Related
I have a WIX installer which updates an SNMP Agent dll. I have a custom action which stops the SNMP service. When the installer runs the log file always says the file is in use when it is not. When reviewing the installer log the log entries appear to be bassackwards. File copy log entries are written after the installed services and SNMP service have all already started. The file is updated and the SNMP Service starts with the newly copied file. No reboot is necessary however MSI is setting the reboot flag. Here's a snippet of my log file. Can anyone make sense of this order of operations issue?
`
...
Action ended 14:59:57: StopSnmpService. Return value 1.
...
MSI (s) (4C:04) [14:59:58:982]: Doing action: InstallFiles
...
MSI (s) (4C:04) [14:59:59:029]: Doing action: InstallServices
Action 14:59:59: InstallServices. Installing new services
Action start 14:59:59: InstallServices.
InstallServices: Service:
Action ended 14:59:59: InstallServices. Return value 1.
MSI (s) (4C:04) [14:59:59:029]: Doing action: StartServices
Action 14:59:59: StartServices. Starting services
Action start 14:59:59: StartServices.
StartServices: Service: Starting services
Action ended 14:59:59: StartServices. Return value 1.
...
MSI (s) (4C:04) [14:59:59:045]: Doing action: StartSnmpService
...
MSI (s) (4C:04) [14:59:59:560]: File: C:\Program Files\Corner Bowl\Server Manager 2022\cbsmsnmpagent.dll; Overwrite; Won't patch; Existing file is a lower version
MSI (s) (4C:04) [14:59:59:560]: Source for file 'cbsmsnmpagent.dll' is compressed
InstallFiles: File: cbsmsnmpagent.dll, Directory: C:\Program Files\Corner Bowl\Server Manager 2022, Size: 19968
MSI (s) (4C:04) [14:59:59:560]: Re-applying security from existing file.
Info 1603. The file C:\Program Files\Corner Bowl\Server Manager 2022\cbsmsnmpagent.dll is being held in use. Close that application and retry.
MSI (s) (4C:04) [15:00:02:919]: Verifying accessibility of file: cbsmsnmpagent.dll
...
`
This is a downside of reinventing the wheel with a custom action. If you used the ServiceControl element then MSI would know that this service will be stopped and the file won't really be in use. But since your doing it out of process with custom code it doesn't know this and you get an erroneous message.
I am creating an MSI installer, during testing the same if I am running the installer for the first time the installer works as expected. But when I accidentally run the installer, it uninstalled my files.
So, for that, I had modified the condition and added Remove="All" in the condition of the actions.
Which is working fine, but I want to show a message to the User that the product is already installed.
So, for that, I added the below piece of code:
<Upgrade Id='<<Upgrade Code>>'>
<UpgradeVersion OnlyDetect='yes' Property='SELFFOUND'
Minimum='1.0.1' IncludeMinimum='yes' Maximum='1.0.1' IncludeMaximum='yes' />
<UpgradeVersion OnlyDetect='yes' Property='NEWERFOUND'
Minimum='1.0.1' IncludeMinimum='no' />
</Upgrade>
<CustomAction Id='AlreadyUpdated' Error='[ProductName] is already installed.' />
.....
.....
.....
.....
.....
<InstallExecuteSequence>
<Custom Action='AlreadyUpdated' After='FindRelatedProducts'>SELFFOUND</Custom>
</InstallExecuteSequence>
But when running this, the installer is still running for the second time and not giving the message.
On checking the logs, could see that the "FindRelatedProducts" skipped with the below message:
MSI (c) (F4:1C) [06:18:04:806]: Doing action: FindRelatedProducts
MSI (c) (F4:1C) [06:18:04:806]: Note: 1: 2205 2: 3: ActionText
Action 6:18:04: FindRelatedProducts. Searching for related applications
Action start 6:18:04: FindRelatedProducts.
MSI (c) (F4:1C) [06:18:04:806]: Skipping FindRelatedProducts action: not run in maintenance mode
Action ended 6:18:04: FindRelatedProducts. Return value 0.
and
MSI (s) (18:14) [06:18:05:500]: Running ExecuteSequence
MSI (s) (18:14) [06:18:05:500]: Doing action: FindRelatedProducts
MSI (s) (18:14) [06:18:05:500]: Note: 1: 2205 2: 3: ActionText
Action 6:18:05: FindRelatedProducts. Searching for related applications
Action start 6:18:05: FindRelatedProducts.
MSI (s) (18:14) [06:18:05:507]: Skipping FindRelatedProducts action: already done on client side
Action ended 6:18:05: FindRelatedProducts. Return value 0.
The condition in AlreadyUpdated custom action also does not satisfy.
MSI (s) (18:14) [06:18:05:737]: Doing action: PublishProduct
MSI (s) (18:14) [06:18:05:737]: Note: 1: 2205 2: 3: ActionText
Action 6:18:05: PublishProduct. Publishing product information
Action start 6:18:05: PublishProduct.
PublishProduct:
MSI (s) (18:14) [06:18:05:752]: Re-publishing product - installing new package with existing product code.
Action ended 6:18:05: PublishProduct. Return value 1.
MSI (s) (18:14) [06:18:05:752]: Skipping action: AlreadyUpdated (condition is false)
Is there any way to achieve this requirement? Am I doing something wrong?
Custom Action Complexity: First a word on custom actions and their complexity. Please read the first paragraphs here:
Why is it a good idea to limit the use of custom actions in my WiX / MSI setups?
Wrong Conditioning: This basically means your conditions are incorrect so the custom actions run in installation modes where they should not. There are many installation modes you should test in when you try to use complex conditions (or any condition for that matter): 1. fresh install, 2. repair, 3. modify, 4. self-repair, 5. patching, 6. uninstall, 7. major upgrade invoked uninstall, etc...
In your case some custom actions run on maintenance run as well as during fresh / first installation. This is a very common problem. The solution is either to eliminate the custom actions by improving the setup, or to improve conditions so they actually work in any installation mode. Obviously.
Condition Debugging: Conditions are hard to get right. I like to test them using message boxes. The bottom section here shows how you can do so: How to execute conditional custom action on install and modify only? - then you run the setup in different modes and look for the dialog boxes. When they show up the condition on the custom action is true.
Complex Conditions:
Here is an answer on why old custom actions are used for a new setup: Wix Tools update uses old custom actions.
There is also an answer listing some values for common properties in different installation modes: How to add a WiX custom action that happens only on uninstall (via MSI)?
Installshield has this PDF of common conditions (some of which are Installshield-specific): https://resources.flexera.com/web/pdf/archive/IS-CHS-Common-MSI-Conditions.pdf
Unexpected Behavior: A special note on the properties UPGRADINGPRODUCTCODE and WIX_UPGRADE_DETECTED. Please read this: Run Wix Custom action only during uninstall and not during Major upgrade - these quirks affect how many times a custom action runs during a major upgrade scenario. Some very surprising effects here for people. Use your message box debugging?
Links:
wix installer update process and confirmation dialog
Wix custom uninstallation action - how to run before msi removing files
Installing driver using cutomAction DriverPackageInstall in wix installer
WIX CustomAction conditions
Failed to get MSI property in UPGRADINGPRODUCTCODE, WIX_UPGRADE_DETECTED
Reboot on install, Don't reboot on uninstall
I have an MSI application with 2 versions v1 and v2 created using InstallShield 2011.
The application executes a SQL script (AddRoleMember.sql)
error 27505: Could not open SQL script file
AddRoleMember.sql executes successfully through v1 but throws an error in v2 for the same user with similar rights and permissions.
AddRoleMember.sql succeeds to execute in v2 only when v2 MSI is executed with Run as Admin command.
The SQL script is same for the both the installers.
There are no changes in v2 from v1 execpt ProductCode and ProductVersion.
Findings from troubleshooting:
Logs from v1 (success):
{
InstallShield 12:14:01: Setting Costing Info Location ISSearchReplaceRollback : C:\Users\APPCSE~1\AppData\Local\Temp\~18F9.tmp
MSI (s) (E8!AC) [12:14:01:445]: PROPERTY CHANGE: Adding ISSearchReplaceRollback property. Its value is'C:\Users\APPCSE~1\AppData\Local\Temp\~18F9.tmp'.
Action ended 12:14:01: ISSearchReplaceCosting. Return value 1.
MSI (s) (E8:F8) [12:14:01:445]: Doing action:ISSQLServerCosting
Action 12:14:01: ISSQLServerCosting.
Action start 12:14:01: ISSQLServerCosting.
MSI (s) (E8:04) [12:14:01:445]: Invoking remote custom action. DLL: C:\Windows\Installer\MSI195B.tmp, Entrypoint: ISSQLServerCosting
1: Beginning SQL Server Costing Process...
1: Reading the SQL script data from ISSQLConnection table...
1: Finished SQL Server Costing Process...
1: Setting Costing Info Location ISSQLServerInstall : C:\Users\APPCSE~1\AppData\Local\Temp\~1948.tmp
MSI (s) (E8!A8) [12:14:01:508]: PROPERTY CHANGE: Adding ISSQLServerInstall property. Its value is 'C:\Users\APPCSE~1\AppData\Local\Temp\~1948.tmp'.
}
Logs from v2 (failed):
{
InstallShield 17:45:50: Setting Costing Info Location ISSearchReplaceRollback : C:\Users\APPCSE~1\AppData\Local\Temp\~96CD.tmp
MSI (s) (34!AC) [17:45:50:900]: PROPERTY CHANGE: Adding ISSearchReplaceRollback property. Its value is 'C:\Users\APPCSE~1\AppData\Local\Temp\~96CD.tmp'.
Action ended 17:45:50: ISSearchReplaceCosting. Return value 1.
MSI (s) (34:54) [17:45:50:900]: Doing action: ISSQLServerCosting
Action 17:45:50: ISSQLServerCosting.
Action start 17:45:50: ISSQLServerCosting.
MSI (s) (34:FC) [17:45:50:916]: Invoking remote custom action. DLL: C:\Windows\Installer\MSI9736.tmp, Entrypoint: ISSQLServerCosting
1: Beginning SQL Server Costing Process...
1: Reading the SQL script data from ISSQLConnection table...
1: Finished SQL Server Costing Process...
1: Setting Costing Info Location ISSQLServerInstall : C:\Windows\TEMP\~97C8.tmp
MSI (s) (34!B4) [17:45:51:180]: PROPERTY CHANGE: Adding ISSQLServerInstall property. Its value is 'C:\Windows\TEMP\~97C8.tmp'.
}
It can be seen from the logs that after the execution of "ISSQLServerCosting" action, the path of Temp location changes in the case of failed installation. The path changes from user specific location to the machine location. Due to this, SQL script succeeds to execute only when executed as Run as Admin. In v1, the path fro Temp location remains user specific before and after the execution of "ISSQLServerCosting" action.
Question: Can anyone please suggest what might be the reason of this change in path in one of the installation? This is the major cause of failure of SQL script in my MSI project.
In the first log the temp is the user temp directory, and in the second it's the system temp directory. Since that action appears to be a custom action, and assuming that nothing else has changed, the first install may have been per-user and the second a per-system.
It's not clear what elevation may or may not have occurred: an MSI configured for elevation will show that elevation dialog after the UI sequence. I'd guess that the first was per-user and didn't need elevation and the second was per system and does need elevation (to access the system temp location).
In my wix I use the following declaration:
<ComponentGroup Id="BinComponents" Directory="BIN">
<Component Id="BinComponent" Guid="23D229D0-06EE-49f4-80B4-6D7136500721">
<File Id="MyProjectOutput" Name="MyProject.exe" Source="MyProject\bin\MyProject.exe"/>
<ServiceControl Id="RemoveService"
Stop="both"
Remove="both"
Name="MyProject.exe"
Wait="yes" /> <!-- Stop running MyProject instances -->
</Component>
</ComponentGroup>
My Repro:
At first, I run my installation as usual. After the installation, I start my web application. An .exe appears in the task manager as usual:
I want to end this .exe on a repair, update or uninstall. So I start my .msi again and choose repair:
Now my problem: After pressing 'Repair', I expect the following dialog because of the declared ServiceControl:
But it doesn´t. Instead, the following dialog appears:
When I log the setup, the log shows the following lines:
MSI (s) (A8:DC) [10:16:28:227]: Executing op: ActionStart(Name=StopServices,Description=Stopping services,Template=Service: [1])
Action 10:16:28: StopServices. Stopping services
MSI (s) (A8:DC) [10:16:28:228]: Executing op: ProgressTotal(Total=1,Type=1,ByteEquivalent=1300000)
MSI (s) (A8:DC) [10:16:28:228]: Executing op: ServiceControl(,Name=MyProject.exe,Action=2,Wait=1,)
MSI (s) (A8:DC) [10:16:28:228]: Executing op: ActionStart(Name=DeleteServices,Description=Deleting services,Template=Service: [1])
Action 10:16:28: DeleteServices. Deleting services
MSI (s) (A8:DC) [10:16:28:228]: Executing op: ProgressTotal(Total=1,Type=1,ByteEquivalent=1300000)
MSI (s) (A8:DC) [10:16:28:229]: Executing op: ServiceControl(,Name=MyProject.exe,Action=8,Wait=1,)
MSI (s) (A8:DC) [10:16:28:229]: Executing op: ActionStart(Name=InstallFiles,Description=Copying new files,Template=File:
[1], Directory: [9], Size: [6])
[...]
MSI (s) (7C:28) [09:06:21:950]: RESTART MANAGER: Did detect that a critical application holds file[s] in use, so a reboot will be necessary.
MSI (s) (7C:28) [09:06:21:950]: Note: 1: 1610
MSI (s) (7C:28) [09:06:21:950]: Note: 1: 2205 2: 3: Error
MSI (s) (7C:28) [09:06:21:950]: Note: 1: 2228 2: 3: Error 4: SELECT `Message` FROM `Error` WHERE `Error` = 1610
Next to a Repair I also have tried an Update with the same results.
Perhaps any declaration missing?
Note: When I close the MyApp.exe in the task manager, the message does not appear, so the MyApp.exe is definitely responsible for the problem.
You should post the entire log somewhere. The root cause is that a repair shouldn't routinely require files to be replaced. So if you literally installed your product, ran the exe, and then a repair needs to replace files, then the issue is not that files-in-use dialog - it's that the installed product is broken, so required files or registry entries have been removed. The application event log should have MsiInstaller entries that describe a missing component. So look at that root cause first.
After fixing that it should be very rare for a repair to need to replace files, so it may not be worth worrying about. But you could look at integrating your app with Restart Manager or using the WiX util CloseApplication.
The warning dialog that you are seeing is from "InstallValidate" standard action.
I have run into a similar issue in the past . I fixed it by making use of a single service control element instead of multiple service control elements, for the same service id.
In my case, i had multiple service control elements for the same service id.
This is as per the link at
http://windows-installer-xml-wix-toolset.687559.n2.nabble.com/Upgrade-uninstall-restart-issue-td7586315.html
This did the trick for me. Numerous users have reported the same behavior, though its not officially documented.
Having a single service control element makes Restart Manager take note of the entry in the Service Control table and will prevent Restart Manager from listing the service in the RMFilesInUse dialog box or will prevent Restart Manager
from throwing up warning messages informing the user that a restart might be required.
Here is one more link
Can't start windows service with WiX
My experiments have shown me that there is definitley a link between the number of service control elements and Restart Manager
http://microsoft.public.windows.msi.narkive.com/OOuQQAsw/controlling-restart-manager-behaviour
The other option was to totally disable Restart Manager using the property RESTARTMANAGERCONTROL, In case, you disable the RestartManager, you might be prompted for reboots(you might want to test it once) and the legacy "Files in Use" mechanism kicks off. Disabling Restart Manager is a conscious decision by the concerned msi developer and at times becomes necessary.
I am not sure about how your Service Control table looks like. Just wanted to share my experience with you.
Hopefully it helps.
Regards,
Kiran Hegde
Someone told me there was a way for the CustomAction in WIX to display the output in the console log. I'm including an .exe called XmlPreprocess.exe to manipulate my web.config, based on parms in a file called SettingsFileGenerator.xml,
I'm running like this:
msiexec /i bin\Debug\TFBIC.RCT.WCFWebServicesWIXSetup.msi /L*V "C:\logs\WixInstall01.log"
This is my WIX build file:
<CustomAction Id="**SAMPLE_CONFIG**" BinaryKey="XMLPREPROCESS" ExeCommand="/i:"[INSTALLLOCATION]web.config" /x:"[INSTALLLOCATION]SettingsFileGenerator.xml" /e:QA /d:ServiceLocation=[SERVICELOCATION]" Execute="deferred" />
<Binary Id="XMLPREPROCESS" SourceFile="../TFBIC.RCT.WCFWebServices/RequiredBins/XMLPreprocess.exe" />
<InstallExecuteSequence>
<Custom Action="SAMPLE_CONFIG" After="StartServices"><![CDATA[NOT Installed]]></Custom>
</InstallExecuteSequence>
Install log shows this:
Action 15:22:27: StartServices. Starting services
Action start 15:22:27: StartServices.
MSI (s) (58:CC) [15:22:27:898]: Note: 1: 2205 2: 3: ServiceControl
MSI (s) (58:CC) [15:22:27:898]: Note: 1: 2228 2: 3: ServiceControl 4: SELECT `Name`,`Wait`,`Arguments`,`Event`, `Action` FROM `ServiceControl`, `Component` WHERE `Component_` = `Component` AND (`Action` = 0 OR `Action` = 1 OR `Action` = 2)
Action ended 15:22:27: StartServices. Return value 1.
MSI (s) (58:CC) [15:22:27:899]: Doing action: SAMPLE_CONFIG
Action 15:22:27: SAMPLE_CONFIG.
Action start 15:22:27: **SAMPLE_CONFIG**.
SAMPLE_CONFIG:
Action ended 15:22:27: **SAMPLE_CONFIG**. Return value 1.
This is my very first attempt to do WIX, so please bear with my ignorance.
Thanks
UPDATE:
This is a quote from another forum - but he doesn't specify how it works and he doesn't seem to check back often.
WiX has a custom action that captures
the console output and sticks it
directly into the verbose MSI log, so
that's what I use.
reference: http://xmlpreprocess.codeplex.com/Thread/View.aspx?ThreadId=79454
Would this be the tool he is talking about?
http://wix.sourceforge.net/manual-wix2/qtexec.htm
I get this error when trying it:
error LGHT0103: The system cannot find the file 'wixca.dll'.
I have searched entire disk for this .dll and could not find it.
To enable all possible logging while installing an msi, use the /lvx* logfile.txt option. However, even this will not log the STDOUT and STDERR output of command line applications invoked as a custom action.
If you have written the custom action yourself, you can add such logging to it. For example, the DTF libraries that come with wix have a handy Session.Log method that you can call. See c:\program files\windows installer xml v3\doc\dtf.chm, topic "Writing Managed Custom Actions" for more information.
If you have not written the application, you could write a custom action to wrap it. Such a wrapper could use the .NET Process class to invoke an executable, read the StandardError and StandardOutput streams, and log everything with the Session.Log method mentioned above.
edit: I don't know of any standard custom action in wix that sends console output to the log. Try the wix-users mailing list.
In Wix 3.10 you can use the Quiet Execution custom action to run an executable (silently, e.g. without a command window popup), and the console output will end up in the msi log.
As mentioned, you need the WixUtilExtension reference to get access to this feature.