Installer flags file in use when it is not - wix

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.

Related

Unable to uninstall the application which is installed using wix installer

I have used wix installer to create an installer for my c# application.
Installation happened fine, but I am not able to uninstall the application. I see below the logs
MSI (s) (78:AC) [15:32:06:199]: Machine policy value 'Debug' is 0
MSI (s) (78:AC) [15:32:06:199]: ******* RunEngine:
******* Product: C:\wix\Installer\\bin\Debug\MyService-Debug-x86.msi
******* Action:
******* CommandLine: **********
MSI (s) (78:AC) [15:32:06:207]: Machine policy value 'DisableUserInstalls' is 0
MSI (s) (78:AC) [15:32:06:326]: Note: 1: 2203 2:
C:\Windows\Installer\inprogressinstallinfo.ipi 3: -2147287038
MSI (s) (78:AC) [15:32:06:327]: Machine policy value
'LimitSystemRestoreCheckpointing' is 0
MSI (s) (78:AC) [15:32:06:327]: Note: 1: 1717 2: My Service (32bit)
MSI (s) (78:AC) [15:32:06:327]: Note: 1: 2205 2: 3: Error
MSI (s) (78:AC) [15:32:06:327]: Note: 1: 2228 2: 3: Error 4: SELECT
`Message` FROM `Error` WHERE `Error` = 1717
MSI (s) (78:AC) [15:32:06:327]: Calling SRSetRestorePoint API.
dwRestorePtType: 1, dwEventType: 102, llSequenceNumber: 0, szDescription:
"Removed My Service (32bit)".
MSI (s) (78:AC) [15:32:06:330]: The System Restore service is disabled.
Returned status: 1058. GetLastError() returned: 1058
MSI (s) (78:AC) [15:32:06:332]: File will have security applied from OpCode.
MSI (s) (78:AC) [15:32:06:362]: SOFTWARE RESTRICTION POLICY: Verifying
package --> 'C:\wix\Installer\\bin\Debug\MyService-Debug-x86.msi' against
software restriction policy
MSI (s) (78:AC) [15:32:06:363]: Note: 1: 2262 2: DigitalSignature 3:
-2147287038
MSI (s) (78:AC) [15:32:06:363]: SOFTWARE RESTRICTION POLICY:
C:\wix\Installer\\bin\Debug\MyService-Debug-x86.msi is not digitally signed
MSI (s) (78:AC) [15:32:06:365]: SOFTWARE RESTRICTION POLICY:
C:\wix\Installer\\bin\Debug\MyService-Debug-x86.msi is permitted to run at
the 'unrestricted' authorization level.
MSI (s) (78:AC) [15:32:06:366]: MSCOREE not loaded loading copy from
system32
MSI (s) (78:AC) [15:32:06:374]: End dialog not enabled
MSI (s) (78:AC) [15:32:06:374]: Original package ==>
C:\wix\Installer\\bin\Debug\MyService-Debug-x86.msi
MSI (s) (78:AC) [15:32:06:374]: Package we're running from ==>
C:\Windows\Installer\152e2e.msi
While creating an installer, I never thought of digitally signing and all. Is it anything to do with signing? Totaly lost and need help
I have even tried with running uninstallation using the command line (admin mode) but no luck
msiexec.exe /x "C:\wix\Installer\\bin\Debug\MyService-Debug-x86.msi" /L*V "C:\work\wix.log"
it says
Another version of this product is already installed. Installation of this version cannot continue. To configure or remove the existing version of this product, use Add/Remove Programs on the Control Panel.
I might have to rebuild the installer code before uninstalling. Is it possible that some "guid" has changed related to the installer? anything I have to check inside registry?
Updated the question with Wix Code
The issue started appearing after I added custom actions. The responsibility of custom action is to get parameters from the installer and update the appsettings.json. but this uninstallation issue not allowing me to continue implementation.
<Property Id="APPLICATIONLOG.PATHFORMAT" Secure="yes"/>
<Binary Id="CustomActionDLL"
SourceFile="..\..\Installer\CustomActions\bin\$(var.Configuration)\CustomAction.CA.dll" />
<CustomAction Id="SetPropertyAppLogPathId"
Property="SetPropertyAppLogPathProperty"
Value="APPLICATIONLOG.PATHFORMAT=[APPLICATIONLOG.PATHFORMAT]"/>
<CustomAction Id="SetPropertyAppLogPathProperty"
BinaryKey="CustomActionDLL"
DllEntry="UpdateConfigurationsAction"
Execute="deferred"
Return="check"
Impersonate="no" />
<InstallExecuteSequence>
<Custom Action="SetPropertyAppLogPathId" Before="SetPropertyAppLogPathProperty"><![CDATA[NOT Installed]]></Custom>
<Custom Action="SetPropertyAppLogPathProperty" After="InstallFiles"></Custom>
</InstallExecuteSequence>
My Custom Action c# code
public class CustomActions
{
public static string ApplicationPath { get; private set; }
[CustomAction]
public static ActionResult UpdateConfigurationsAction(Session session)
{
try
{
session.Log("Begin UpdateConfigurationsAction");
ApplicationPath = session.CustomActionData["APPLICATIONLOG.PATHFORMAT"];
session.Log("Application Log Path is: " + ApplicationPath);
return ActionResult.Success;
}
catch (Exception e)
{
session.Log("Error in UpdateConfigurationsAction " + e.Message);
return ActionResult.Failure;
}
}
}
Issue Resolved
The issue was with the custom action. After making proper InstallExecuteSequence it worked!
Will update in solution section
Cross-Link: How to clean out broken uninstalls.
Microsoft FixIt: Before trying anything else, perhaps try the Microsoft FixIt tool to see if you can get rid of any
dangling installations. If unsuccessful check further down for other
approaches.
Debugging & Logging: Next fix your custom action in the package based on custom action debugging (I recommend the Advanced Installer MSI CA debugging video, it is quick and a good "hello debugger" session) and gathering logging information.
Countermeasure: Finally, maybe add a property to suppress the custom action from running as described here ("Adding Condition" section).
This is the simplest
idea I know of to suppress custom actions from running on uninstall - you just set the property involved when needed to suppress the custom action if it crashes. >
I would use it for all my custom actions - in fact - so I can suppress them all (or
maybe one by one) - especially for uninstall scenarios where you run into "catch 22" situations (unable to install, upgrade or uninstall due to custom action bugs).
Dangling Installations: In order to detect all related, dangling installations (if any), you can use this approach: Unable to uninstall program from WiX created MSI (enumerate all products with the same upgrade code).
I will add these links for now in case you find that dangling version:
wix - custom action dialogbox on silent uninstall of application
I screwed up, how can I uninstall my program?
When trying to remove an MSI which crashes on uninstall, the central question is how many computers are involved? If it is just one, then hacking the cached MSI database may be acceptable, otherwise you should create a patch package to fix the uninstall sequence and then trigger uninstall the normal way.
Links:
Throwing in one more link: WIX does not uninstall older version. It is possible to have installations per-user or per-machine.

InstallShield 2011: "ISSQLServerCosting" action changes Temp path. Error pops up: Could not open SQL script file <SQL script filename>

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).

How can I stop an .exe on repair, update and delete in wix?

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

Wix MSI fails when setting permissions on network path (util:PermissionEx)

I have an MSI that works perfectly when installing locally. If the data path is set to a network location, it fails.
Relevant LOG:
MSI (s) (BC:4C) [17:01:57:322]: Executing op: ActionStart(Name=ExecSecureObjects_64,,)
MSI (s) (BC:4C) [17:01:57:322]: Executing op: CustomActionSchedule(Action=ExecSecureObjects_64,ActionType=3073,Source=BinaryData,Target=ExecSecureObjects,CustomActionData=\\ravel\TeamData\lrieger\Tim2015Pre_Data\CreateFolderEveryone-1073741824C:\ProgramData\Nemetschek Engineering\TIM 2015.0.0.477590057-pre\CreateFolderEveryone-1073741824)
MSI (s) (BC:78) [17:01:57:324]: Invoking remote custom action. DLL: C:\Windows\Installer\MSIAEDE.tmp, Entrypoint: ExecSecureObjects
MSI (s) (BC:A8) [17:01:57:324]: Generating random cookie.
MSI (s) (BC:A8) [17:01:57:325]: Created Custom Action Server with PID 4488 (0x1188).
MSI (s) (BC:60) [17:01:57:335]: Running as a service.
MSI (s) (BC:60) [17:01:57:337]: Hello, I'm your 64bit Elevated custom action server.
ExecSecureObjects: Error 0x80070005: failed to get security info for object: \\ravel\TeamData\lrieger\Tim2015Pre_Data\
CustomAction ExecSecureObjects_64 returned actual error code 1603 (note this may not be 100% accurate if translation happened inside sandbox)
MSI (s) (BC:4C) [17:01:57:393]: Note: 1: 2265 2: 3: -2147287035
MSI (s) (BC:4C) [17:01:57:393]: User policy value 'DisableRollback' is 0
MSI (s) (BC:4C) [17:01:57:393]: Machine policy value 'DisableRollback' is 0
Action ended 17:01:57: InstallExecute. Return value 3.
WIX Code:
<Component Directory="DATA_DIRECTORY">
<RegistryValue Root="HKLM" Key="$(var.RegRoot)\Setup" Name="TIM_DATA_DIRECTORY" Value="0xff" Type="string" />
<CreateFolder>
<util:PermissionEx User="Everyone" GenericRead="yes" GenericWrite="yes" Domain="[LOGONDOMAIN]" />
</CreateFolder>
</Component>
Without the util:PermissionEx it works on the network share, but setting these permissions is a requirement, at least if the target directory is local.
Q: Is it possible to set permissions on a network location with wix/msi?
If Not, how can I detect that it is a network directory?
Or is there, in MSI, any way to mark a component as allowed to fail?
If it is not possible to do any of the above, I will probably need to write a custom action that tries to set the permissions but suppresses any failures...
Briefly, I don't think it's possible. The issue is that elevated custom actions run with the system account, and that account doesn't have any network privileges. That WiX utils code is already a custom action that's supplied as a helper for a common task, so writing your own custom action isn't going to help. If you run the CA not impersonated it won't run elevated (unless you elevate the entire MSI install at launch time) so that's not likely to help either. You need an elevated user app to do this for the network share, maybe run at first use of the app itself. This might help:
http://wixtoolset.org/documentation/manual/v3/howtos/ui_and_localization/run_program_after_install.html
I would assume it's a network share if it starts with \. A drive letter won't work with the CA anyway because drive letters are a user profile mapping (not a system mapping), so the system account won't know of them. In .Net, FileSystem.GetDriveInfo would help.

How to debug WiX installer

I am adding to build to your WiX installer to include a multi-website deployment based on custom dialog selection.
I am running into this issue when i run in debug mode and not sure how to tackle the problem to find what the issue is, I am getting a Failed to load XML Error:
MSI (s) (D0:60) [10:25:14:945]: Executing op:
ActionStart(Name=ExecXmlFile,,) Action 10:25:14: ExecXmlFile.
MSI (s) (D0:60) [10:25:14:960]: Executing op:
CustomActionSchedule(Action=ExecXmlFile,ActionType=3073,Source=BinaryData,Target=ExecXmlFile,CustomActionData=20C:\Program
Files\Company Name,
Inc\18.4.007\Navigator\bin\hibernate.cfg.xml30//property[#name='connection.connection_string_name']Workbench_PROD2130/
+ MORE SIMILAR STUFF
MSI (s) (D0:30) [10:25:14:976]: Invoking remote custom action. DLL:
C:\Windows\Installer\MSI5E32.tmp, Entrypoint: ExecXmlFile
MSI (s) (D0:B0) [10:25:14:976]: Generating random cookie.
MSI (s) (D0:B0) [10:25:14:976]: Created Custom Action Server with PID
3980 (0xF8C).
MSI (s) (D0:8C) [10:25:15:163]: Running as a service.
MSI (s) (D0:8C) [10:25:15:163]: Hello, I'm your 32bit Elevated custom
action server.
ExecXmlFile: Error 0x8007006e: failed to load XML file:
Since your error occurs when running a custom action, I would add a Debugger.Launch(); for C# or s.t. equivalent for other languages at the very start of your custom action method. This would allow you to debug in Visual Studio as usual.
The only advice I can give you is to use Orca, which is a low-level tool for creating and editing MSI file. At least it will validate your msi and show you any errors or warnings it finds.