In the released MSI, I had the hard-coded port number, e.g.
<Property Id="HTTP_PORT1" Secure="yes" Value="1000" />
<Component Id="my.exe" Guid="*" Win64="yes" >
<File Id="my.exe" KeyPath="yes" Source="my.exe" />
<RegistryValue Root="HKLM" Key="SOFTWARE\MyCompany" Name="Port1" Value="[HTTP_PORT1]" Type="integer" />
<RegistryValue Root="HKLM" Key="SOFTWARE\MyCompany" Name="Port2" Value="9000" Type="integer" />
</Component>
And for the patch, my Patch.wxs looked like this:
<PatchFamily Id="Rollup" Version="1.0.100" Supersede="yes">
<ComponentRef Id="my.exe"/>
</PatchFamily>
When I manually change those regs to "1111" and "9999" and applied the patch MSP, those Port1 and Port2 were set back to "1000" and "9000" respectively. So I changed "HTTP_PORT1" and added "INT_HTTP_PORT2" like this:
<Property Id="HTTP_PORT1" Secure="yes" Value="#1000" >
<RegistrySearch Root="HKLM" Key="SOFTWARE\MyCompany" Name="Port1" Type="raw" Win64="yes" />
</Property>
<Property Id="INT_HTTP_PORT2" Secure="yes" Value="#9000" >
<RegistrySearch Root="HKLM" Key="SOFTWARE\MyCompany" Name="Port2" Type="raw" Win64="yes" />
</Property>
<Component Id="my.exe" Guid="*" Win64="yes" >
<File Id="my.exe" KeyPath="yes" Source="my.exe" />
<RegistryValue Root="HKLM" Key="SOFTWARE\MyCompany" Name="Port1" Value="[HTTP_PORT1]" Type="string" />
<RegistryValue Root="HKLM" Key="SOFTWARE\MyCompany" Name="Port2" Value="[INT_HTTP_PORT2]" Type="string" />
</Component>
And I changed Patch.wxs like this:
<PatchFamily Id="Rollup" Version="1.0.100" Supersede="yes">
<ComponentRef Id="my.exe"/>
<PropertyRef Id="HTTP_PORT1"/>
<PropertyRef Id="INT_HTTP_PORT2"/>
</PatchFamily>
However, both Port1 and Port2 are changed back to the original values (although Port1 is now REG_SZ.)
Is this an expected behavior? Is it possible to make it work in the patch without using Type1 custom action?
The executable in that component is the keypath item. I'd verify that you increased the version of that exe because it effectively controls whether that component is updated. You could create a verbose log of the patch install to see exactly what's going on.
What you need to look for in the verbose log is what it says about my.exe, whether it's Overwrite or something else. Also, note that if the component rules were broken in the patch it will effectively result in nothing being patched. You will see SELMGR in the log if that's the case.
Related
I am trying to write a WiX installer that includes a managed icon shell extension (using SharpShell). I've finally figured out how to register it via Wix (I couldn't get the SharpShell registration manager to work whenn called via WiX).
During installation, the following dialog appears:
If I select "Ignore", the icon shell extension is successfully installed and Window Explorer picks up the change immediately. I'm not sure which files that its detecting as "In Use".
During uninstall, the following dialog appears:
If you select the "Automatically close and attempt to restart" option, it closes Windows Explorer, but it does not restart at the end of the installation. I have to manually restart it via task manager.
WiX Fragment Definition
The WiX fragment that defines the shell extension installation is shown below:
<?xml version="1.0" encoding="utf-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi" xmlns:util='http://schemas.microsoft.com/wix/UtilExtension'>
<!-- This fragment was originally generated using heat with the following command line:
"$(WIX)bin\heat.exe" dir "$(SolutionDir)Icon ShellExtension\bin\$(ConfigurationName)" -dr IconShellExtensionDIR -cg IconShellExtension -var var.IconShellExtension.TargetDir -fips -g1 -gg -sfrag -srd -suid -template fragment -t "$(ProjectDir)AssemblyFileFilter.xslt" -out "$(ProjectDir)Fragments\IconShellExtension.wxs"
It was then subsequently manually modified, as file associations are defined in a different component the default icon entry had to be removed.
-->
<Fragment>
<DirectoryRef Id="IconShellExtensionDIR">
<Component Id="IconShellExtension.dll" Guid="D609F6F2-52FB-4153-8D6A-3E2B7F8C4647">
<Class Id="{A1C3600C-F3E5-300E-8167-541C62083DAA}" Context="InprocServer32" Description="IconShellExtension.UaProjectIconHandler" ThreadingModel="both" ForeignServer="mscoree.dll">
<ProgId Id="IconShellExtension.UaProjectIconHandler" Description="UA Project File Icon Handler" />
</Class>
<util:RestartResource ProcessName="explorer.exe"/>
<File Id="IconShellExtension.dll" KeyPath="yes" Source="$(var.IconShellExtension.TargetDir)\IconShellExtension.dll" />
<RegistryValue Root="HKCR" Key="CLSID\{A1C3600C-F3E5-300E-8167-541C62083DAA}\Implemented Categories\{62C8FE65-4EBB-45e7-B440-6E39B2CDBF29}" Value="" Type="string" Action="write" />
<RegistryValue Root="HKCR" Key="CLSID\{A1C3600C-F3E5-300E-8167-541C62083DAA}\InprocServer32\1.0.0.0" Name="Class" Value="IconShellExtension.UaProjectIconHandler" Type="string" Action="write" />
<RegistryValue Root="HKCR" Key="CLSID\{A1C3600C-F3E5-300E-8167-541C62083DAA}\InprocServer32\1.0.0.0" Name="Assembly" Value="IconShellExtension, Version=1.0.0.0, Culture=neutral, PublicKeyToken=9e9ad08f31c5e4fb" Type="string" Action="write" />
<RegistryValue Root="HKCR" Key="CLSID\{A1C3600C-F3E5-300E-8167-541C62083DAA}\InprocServer32\1.0.0.0" Name="RuntimeVersion" Value="v4.0.30319" Type="string" Action="write" />
<RegistryValue Root="HKCR" Key="CLSID\{A1C3600C-F3E5-300E-8167-541C62083DAA}\InprocServer32\1.0.0.0" Name="CodeBase" Value="file:///[#IconShellExtension.dll]" Type="string" Action="write" />
<RegistryValue Root="HKCR" Key="CLSID\{A1C3600C-F3E5-300E-8167-541C62083DAA}\InprocServer32" Name="Class" Value="IconShellExtension.UaProjectIconHandler" Type="string" Action="write" />
<RegistryValue Root="HKCR" Key="CLSID\{A1C3600C-F3E5-300E-8167-541C62083DAA}\InprocServer32" Name="Assembly" Value="IconShellExtension, Version=1.0.0.0, Culture=neutral, PublicKeyToken=9e9ad08f31c5e4fb" Type="string" Action="write" />
<RegistryValue Root="HKCR" Key="CLSID\{A1C3600C-F3E5-300E-8167-541C62083DAA}\InprocServer32" Name="RuntimeVersion" Value="v4.0.30319" Type="string" Action="write" />
<RegistryValue Root="HKCR" Key="CLSID\{A1C3600C-F3E5-300E-8167-541C62083DAA}\InprocServer32" Name="CodeBase" Value="file:///[#IconShellExtension.dll]" Type="string" Action="write" />
<RegistryValue Root="HKCR" Key="UserAppProject\ShellEx\IconHandler" Value="{a1c3600c-f3e5-300e-8167-541c62083daa}" Type="string" Action="write" />
<RegistryValue Root="HKLM" Key="Software\Microsoft\Windows\CurrentVersion\Explorer" Name="GlobalAssocChangedCounter" Value="1" Type="integer" Action="write" />
</Component>
<Component Id="SharpShell.dll" Guid="174E147D-4744-492F-BC5C-F00DAA4925AA">
<File Id="SharpShell.dll" KeyPath="yes" Source="$(var.IconShellExtension.TargetDir)\SharpShell.dll" />
</Component>
</DirectoryRef>
</Fragment>
<Fragment>
<ComponentGroup Id="IconShellExtension">
<ComponentRef Id="IconShellExtension.dll" />
<ComponentRef Id="SharpShell.dll" />
</ComponentGroup>
</Fragment>
</Wix>
Goal
I want the installer to be able to install or uninstall without prompting the user about files in use, and it just auto close and restart Windows Explorer during the process. My understanding is that's what the restart manager allows, and the WixUtils RestartResource tag should do this for me.
Any help would be appreciated!
UPDATE
I have tried various different combinations of properties and attempted to remove/disable the FilesInUse dialog.
I tried setting the following combination of properties as suggested in this post:
<Property Id="MSIRMSHUTDOWN" Value="2"/>
<Property Id="MSIDISABLERMRESTART" Value="0"/>
<Property Id="MSIRESTARTMANAGERCONTROL" Value="0"/>
This performed the restart of explorer.exe during uninstall, once the uninstall sequence was completed (although the length of time the explorer was shutdown for was lengthy). However, I found that when I attempt to reinstall, it displayed the FilesInUse dialog again.
I found a solution that worked for me which I will post as the accepted answer.
The best solution that seemed to work and did not display any unwanted dialogs was to remove the MSIRMSHUTDOWN and MSIDISABLERMRESTART properties and set the following property:
<!-- The following setting seems to suppress any restart dialogs -->
<Property Id="MSIRESTARTMANAGERCONTROL" Value="Disable"/>
This cleanly added or removed my shell extension. The only issue is that the shell extension remained active until I rebooted (as this was an Icon Shell Extension only, then this was acceptable to me).
Note that I'm not asking for a registry value. Just the key. How do I do that with WiX?
The following doesn't work when HKLM\SOFTWARE\Microsoft\VSTO Runtime Setup\v4 key exists:
<Property Id="VSTOINST1">
<RegistrySearch Id="idVsto1" Root="HKLM" Key="SOFTWARE\Microsoft\VSTO Runtime Setup\v4" Type="directory" />
</Property>
<Condition Message="Visual Studio 2010 Tools for Office Runtime is not installed. You can get it from: https://www.microsoft.com/en-us/download/details.aspx?id=56961">
<![CDATA[Installed OR (VSTOINST1)]]>
</Condition>
PS. For clarity I'm testing it on a 32-bit Windows OS.
I create it in this way:
<Directory Id="TARGETDIR" Name="SourceDir">
...
<ComponentGroup Id="REGISTRYENTRIES" Directory="INSTALLFOLDER">
<Component Id="Registry" Guid="..." >
<RegistryKey Root="HKLM" Key="Software\...\..." Action="createAndRemoveOnUninstall">
<RegistryValue Name="Version" Value="[BuildVersioProp]" Type="string" />
<RegistryValue Name="InstallSource" Value="[PATH]" Type="string" />
<RegistryValue Name="Publisher" Value="Comapny" Type="string" />
</RegistryKey >
</Component>
</ComponentGroup>
Product:
<Product>
...
<Feature Id="ProductFeature4" Title="CCC" Level="1" >
<ComponentGroupRef Id="REGISTRYENTRIES" />
</Feature>
</Product>
and add to property:
<Property Id="PATH">
<RegistrySearch Id='my_app_dir' Type='raw' Root='HKLM' Key='SOFTWARE\WOW6432Node\...\...' Name='InstallSource' />
</Property>
I used procrun to create a windows service and tried to install it using WIX. I have placed all the required registry keys at the relevant places. But the service is still not listed in the local services. Below is my code.
<?xml version="1.0" encoding="UTF-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
<Product Id="*" Name="DummyInstaller" Language="1033" Version="1.0.0.0" Manufacturer="Bryan" UpgradeCode="94D1BC64-7CC1-45DA-BD5F-8ED40980E75C">
<Package InstallerVersion="200" Compressed="yes" InstallScope="perMachine" Platform="x64"/>
<Property Id="JAVA_CURRENT_VERSION64">
<RegistrySearch Id="JRE_CURRENT_VERSION_REGSEARCH64" Root="HKLM" Key="SOFTWARE\JavaSoft\Java Runtime Environment" Name="CurrentVersion" Type="raw" Win64="yes" />
</Property>
<MajorUpgrade DowngradeErrorMessage="A newer version of [ProductName] is already installed." />
<MediaTemplate />
<Feature Id="ProductFeature" Title="DummyInstaller" Level="1" >
<!--<ComponentGroupRef Id="NewFilesGroup" />-->
<ComponentRef Id="REGISTRY_A" />
<ComponentRef Id="PROCRUN.EXE"/>
</Feature>
</Product>
<Fragment>
<Directory Id="TARGETDIR" Name="SourceDir">
<Directory Id="ProgramFiles">
<Directory Id="DummyDir" Name="DummyInstaller">
<!--<Directory Id="MyProgramDir" Name="MosquittoNew" />-->
<Directory Id="SERVERDIR" Name="Kube2UpdaterService">
<Component Id="REGISTRY_A" DiskId="1" Guid="*" Win64="no">
<RegistryKey Root="HKLM" Key="SOFTWARE\Apache Software Foundation\Procrun 2.0\Kube2UpdaterService\Parameters\Java" Action="createAndRemoveOnUninstall">
<RegistryValue Type="string" Name="Classpath" Value="E:\Service\Update_Service-1.0.jar" KeyPath="yes" />
<RegistryValue Type="string" Name="Jvm" Value="C:\Program Files\Java\jdk1.8.0_25\jre\bin\server\jvm.dll" />
<RegistryValue Type="multiString" Action="append" Name="Options">
<MultiStringValue Type="multiString" Name="Options" Action="append">-Duser.language=en</MultiStringValue>
<MultiStringValue Type="multiString" Name="Options" Action="append">-Duser.region=US</MultiStringValue>
</RegistryValue>
<RegistryValue Type="integer" Name="JvmMs" Value="256" />
<RegistryValue Type="integer" Name="JvmMx" Value="1024" />
<RegistryValue Type="integer" Name="JvmSs" Value="4000" />
</RegistryKey>
<RegistryKey Root="HKLM" Key="SOFTWARE\Apache Software Foundation\Procrun 2.0\Kube2UpdaterService\Parameters\Log" Action="createAndRemoveOnUninstall">
<RegistryValue Type="string" Name="Path" Value="c:\logs" />
<RegistryValue Type="string" Name="Level" Value="Error" />
<RegistryValue Type="string" Name="Prefix" Value="Kube2UpdaterService" />
<RegistryValue Type="string" Name="StdError" Value="c:\logs\stderr.txt" />
<RegistryValue Type="string" Name="StdOutput" Value="c:\logs\stdout.txt" />
</RegistryKey>
<RegistryKey Root="HKLM" Key="SOFTWARE\Apache Software Foundation\Procrun 2.0\Kube2UpdaterService\Parameters\Start" Action="createAndRemoveOnUninstall">
<RegistryValue Type="string" Name="Mode" Value="jvm" />
<RegistryValue Type="string" Name="Class" Value="com.kohls.kube.services.updater.UpdaterServiceMain" />
<RegistryValue Type="string" Name="Params" Value="start" />
</RegistryKey>
<RegistryKey Root="HKLM" Key="SOFTWARE\Apache Software Foundation\Procrun 2.0\Kube2UpdaterService\Parameters\Stop" Action="createAndRemoveOnUninstall">
<RegistryValue Type="string" Name="Mode" Value="jvm" />
<RegistryValue Type="string" Name="Class" Value="com.kohls.kube.services.updater.UpdaterServiceMain" />
<RegistryValue Type="string" Name="Method" Value="stop" />
<RegistryValue Type="string" Name="Params" Value="stop" />
<RegistryValue Type="string" Name="StdOutput" Value="auto" />
</RegistryKey>
<RegistryKey Root="HKLM" Key="SYSTEM\CurrentControlSet\Services\Kube2UpdaterService" Action="createAndRemoveOnUninstall">
<RegistryValue Type="string" Name="Description" Value="Kube updater service performing updates and installation" />
<RegistryValue Type="string" Name="DisplayName" Value="Kube2UpdaterService" />
<RegistryValue Type="string" Name="ImagePath" Value="E:\Service\prunsrv.exe //RS//Kube2UpdaterService" />
<RegistryValue Type="string" Name="DependsOnService" Value="Tcpip Afd" />
<RegistryValue Type="string" Name="ObjectName" Value="LocalSystem" />
<RegistryValue Type="integer" Name="ErrorControl" Value="1" />
<RegistryValue Type="integer" Name="Start" Value="2" />
<RegistryValue Type="integer" Name="Type" Value="16" />
</RegistryKey>
<RegistryKey Root="HKLM" Key="SYSTEM\CurrentControlSet\Services\Kube2UpdaterService\Parameters" Action="createAndRemoveOnUninstall">
<RegistryValue Type="string" Name="Test" Value="Pass" />
</RegistryKey>
</Component>
<Component Id="PROCRUN.EXE" DiskId="1" Guid="468C2DB3-F722-4DE6-8A91-B6FB8009757D" Win64="no">
<!-- this is the renamed procrun 64 bit executable -->
<File Id="prunsrv.exe" Name="prunsrv.exe" Source="E:\Service\prunsrv.exe" />
<ServiceInstall Id="PROCRUN" Type="ownProcess" Name="Kube2UpdaterService" DisplayName="Kube2UpdaterService" Description="Kube 2.0 Updater Service" Start="auto" Account="LocalService" ErrorControl="normal" Arguments=" //RS//Kube2UpdaterService" />
<ServiceControl Id="StartPRUNSRV" Start="install" Stop="both" Remove="uninstall" Name="Kube2UpdaterService" Wait="no" />
</Component>
</Directory>
</Directory>
</Directory>
</Directory>
</Fragment>
</Wix>
What am I doing wrong here? Please advice.
All registry keys under HKLM\SYSTEM\CurrentControlSet\Services are considered internal to Windows. The supported way in MSI to configure Windows Services is to use the Service* tables, like ServiceInstall.
Your:
<File Id="prunsrv.exe" Name="prunsrv.exe" Source="E:\Service\prunsrv.exe" />
needs to set be
<File Id="prunsrv.exe" Name="prunsrv.exe" Source="E:\Service\prunsrv.exe" Keypath="yes" />
I don't know why, but it helps
I have a WIX installation setup for a COM DLL that seems to work fine without the MSIUSEREALADMINDETECTION value set to 1. However, I am not sure if it works on all configurations (Windows versions, .NET versions, etc).
Would you include ("Property Id="MSIUSEREALADMINDETECTION" Value="1") in my WIX configuration file just to be 100% sure that the MSI will register the COM DLL correctly in all corner cases?
As I have understood, this property will force the installer to run with "real" administrative rights.
This is for an enterprise application so it is very important the installation goes smooth.
WIX file:
<?xml version="1.0" encoding="UTF-8"?>
<!-- <Property Id="MSIUSEREALADMINDETECTION" Value="1" /> unsure if this is needed yet -->
<Property Id="ARPHELPLINK" Value="http://www.example.com" />
<Property Id="ARPURLINFOABOUT" Value="http://www.example.com" />
<PropertyRef Id="NETFRAMEWORK40FULL" />
<PropertyRef Id="NETFRAMEWORK40CLIENT" />
<Condition Message="This application requires .NET Framework 4.0 or later. Please install the .NET Framework 4.0 or later and then run this installer again.">
<![CDATA[Installed OR NETFRAMEWORK40FULL OR NETFRAMEWORK40CLIENT]]>
</Condition>
<WixVariable Id="WixUIDialogBmp" Value="InstallerBackgroundWix.bmp" />
<WixVariable Id="WixUIBannerBmp" Value="InstallerBannerWix.bmp" />
<Fragment>
<Directory Id="TARGETDIR" Name="SourceDir">
<Directory Id="ProgramFilesFolder">
<Directory Id="INSTALLFOLDER" Name="example">
<Component Id="MyAddin" Guid="guid3" Win64="no">
<File Id="exampleDLL" Source="$(var.example.TargetDir)example.dll"/>
<Class Id="{guid4}" Context="InprocServer32" Description="example" ThreadingModel="both" ForeignServer="mscoree.dll">
<ProgId Id="example" Description="example" />
</Class>
<RegistryValue Root="HKCR" Key="CLSID\{guid4}\Implemented Categories\{62C8FE65-4EBB-45e7-B440-6E39B2CDBF29}" Value="" Type="string" Action="write" />
<RegistryValue Root="HKCR" Key="CLSID\{guid4}\InprocServer32\1.0.0.0" Name="Class" Value="example.Addin" Type="string" Action="write" />
<RegistryValue Root="HKCR" Key="CLSID\{guid4}\InprocServer32\1.0.0.0" Name="Assembly" Value="example, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" Type="string" Action="write" />
<RegistryValue Root="HKCR" Key="CLSID\{guid4}\InprocServer32\1.0.0.0" Name="RuntimeVersion" Value="v4.0.30319" Type="string" Action="write" />
<RegistryValue Root="HKCR" Key="CLSID\{guid4}\InprocServer32\1.0.0.0" Name="CodeBase" Value="file:///[#exampleDLL]" Type="string" Action="write" />
<RegistryValue Root="HKCR" Key="CLSID\{guid4}\InprocServer32" Name="Class" Value="example.Addin" Type="string" Action="write" />
<RegistryValue Root="HKCR" Key="CLSID\{guid4}\InprocServer32" Name="Assembly" Value="example, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" Type="string" Action="write" />
<RegistryValue Root="HKCR" Key="CLSID\{guid4}\InprocServer32" Name="RuntimeVersion" Value="v4.0.30319" Type="string" Action="write" />
<RegistryValue Root="HKCR" Key="CLSID\{guid4}\InprocServer32" Name="CodeBase" Value="file:///[#exampleDLL]" Type="string" Action="write" />
<RegistryKey Root="HKLM" Key="SOFTWARE\Microsoft\Office\Outlook\Addins\example">
<RegistryValue Type="integer" Name="LoadBehavior" Value="3"/>
<RegistryValue Type="string" Name="Description" Value="example Outlook Add-in"/>
<RegistryValue Type="string" Name="FriendlyName" Value="example Outlook Add-in"/>
</RegistryKey>
</Component>
</Directory>
</Directory>
</Directory>
</Fragment>
No, don't use it. It does not give the install any more privilege to do anything. It's a legacy setting that enables older MSI installs to get values for the Privileged and AdminUser values as they were before UAC. In other words if you ask the value of the AdminUser property in the UI sequence (before the UAC prompt) it will tell you "true" if MSIUSEREALADMINDETECTION is set and "false" if it isn't (which is considered the right answer because there's been no elevation prompt so how can the user be Admin?).
Better answer at Mark MSI so it has to be run as elevated Administrator account
Summary: One difference is it changes the user credentials that CustomActions are run under.
The below component does everything as expected, but fails to write the last registry key value. I get no errors.
<Component Id="ProgramMenuDir" Guid="68977683-3F36-45EF-9FF4-7B9461A42D06">
<RemoveFolder Id="ProgramMenuDir" On="uninstall" />
<RegistryKey Root="HKLM" Key="Software\Wow6432Node\[Manufacturer]\[ProductName]" ForceCreateOnInstall="yes" ForceDeleteOnUninstall="yes">
<RegistryValue Type="string" Name="APIUrl" Value="http://api.blah/" KeyPath="yes" />
<RegistryValue Type="string" Name="Token" Value="blah" />
</RegistryKey>
<RegistryKey Root="HKLM" Key="Software\Wow6432Node\[Manufacturer]\[ProductName]\Tokens" ForceCreateOnInstall="yes" ForceDeleteOnUninstall="yes" />
<RegistryKey Root="HKLM" Key="Software\Wow6432Node\[Manufacturer]\[ProductName]\Tokens\WOvN+Lac+d3wRtY0uBUsAeHTYg4x7j2/NWpftWv/16qaOz3J6TpDQmvjUpQmoCWPSFdMpbrcpi4rJd56aBKkkvSR54RsS5xueaYfPgk1QmQ=" ForceCreateOnInstall="yes" ForceDeleteOnUninstall="yes" />
<RegistryValue Root="HKLM" Action="write" Key="Software\Microsoft\Windows\CurrentVersion\Run" Name="[ProductName]" Value="blah" Type="string" />
</Component>
Why no write, yet no errors?
Are you just looking in the wrong place, if this is a 32 bit installer then you need to check the following location - HKLM\Software\Wow6432Node\Microsoft
Remember that these are the equivalent nodes depending on your install architecture:
32bit installer on 64bit machine:
HKLM\Software\Wow6432Node\Microsoft
32bit installer on 32bit machine or 64bit installer on 64bit machine:
HKLM\Software\Microsoft