windows service not removed while uninstalling setup created in WIX - wix

I have created the setup which installs windows service, but when i uninstall it the service remains started and not removes. I have createwd the setup msi in Wix.
<DirectoryRef Id="INSTALLDIR">
<Component Id='MyComponent' Guid='CDBA9BC4-F839-4CAB-8AB0-4397EC079541'>
<File Id='LogFWService' Name='LogFWService.exe' Source="$(var.LFShared)\LogFWService.exe" KeyPath="yes" />
<ServiceInstall Id="InstallLFService" Name="LogFWService" DisplayName="OpenFramework Logging Service" Start="auto" ErrorControl="normal" Description="Captures log events and inserts the log messages into database" Type="ownProcess">
<ServiceDependency Id="MSMQ" />
</ServiceInstall>
<ServiceControl Id="sc_InstallLFService" Name="LogFWService" Start="install" Remove="uninstall" Stop="both" Wait="yes"/>
</Component>
</DirectoryRef>
Even i have used the remove file attribute but it stills doesnot removes the windows service while uninstalling.
Please help is any one have any knowledge about uninstalling windows service.

I had a similar problem. I'm not 100% sure but I think it disappeared after I changed the GUID of the installation component. Previous GUID was copy pasted from another project along with the whole installation markup for installing windows service and I forgot to replace it with new GUID.
BTW You can delete the "leftover" service using command propmt command sc:
sc delete "YourServiceNameHere"

I have had this happen when testing multiple versions of the same wix installer in a development environment. The problem is that it cannot remove an entity (component) because there is a dependency that is still declared. Its usually due to some registry keys being left over from prior attempts.
Searching for the following and deleting the appropriate (not all) keys
The ID of the key file in a component
The GUID of the component
The directory/folder name (can be included reference counts in \HKLM\MS\Win\CurVer\Installer\Folders)
The name of the key file (also reference counts, but not in the Folders key)
Some keys that show up for the name searches tended to be in Most Recently Used lists, or other benign locations. This can be a tedious process when using the standard regedit, so a better tool is recommended if you go this route.
Ideally, you should be testing installers on a machine that can be reverted to a prior state.

Related

Make Wix to not uninstall common dll

I have Wix project in which I need a common used dll library to be installed if it's absent.
If this dll exists I should not overwrite it.
So, when I set DefaultVersion="0.0.0.0" this dll is not overwritten if it exists, its ok. But when I delete app, the dll is beeing removed. How do I prevent removing dll in the case when it existed before installation?
I don't want to make it permanent because it should be removed if it didn't exist before installation.
<Component Id="myLib.dll" Permanent="no" Directory="Shared_Dir">
<File Name="myLib.dll" KeyPath="yes"
Source="mySource\myLib.dll"
DefaultVersion="0.0.0.0"
/>
Add reference to WixUtilExtension and xmlns:util="http://schemas.microsoft.com/wix/UtilExtension" attribute to Wix element in your code.
Define <Property Id="Dll_Installed" Value="false"/> in Product element.
Add child <Condition>NOT Dll_Installed</Condition> to component myLib.dll.
Add that somewhere in your code:
<Fragment>
<util:FileSearch
Id="Dll_Installed"
Variable="Dll_Installed"
Path="[Shared_Dir]myLib.dll"
Result="exists"/>
</Fragment>
DefaultVersion attribute is not necessary.
The feature you are describing is reference counting. The Windows Installer reference counts with Components. Components are identified by their GUID.
So the normal way to address this requirement is to put the File in a Component and make sure the GUID of the Component is stable. The WiX Toolset should do exactly that automatically if if you do not specify the Component/#Guid attribute.
So the default behavior should just work for you.
The only other piece of the puzzle is the Windows Installer will install the latest version of a file. If the file version is the same or less the file will not be installed but will be reference counted.
Based on the details in the question it seems like you should be just fine with:
<Component Directory="Shared_Dir">
<File Source="mySource\myLib.dll" />
</Component>
One might ask why the Windows Installer use Components to reference count files. We'll, it allows you to group other resources, like registry keys, together and control their install as a unit. Much more important if you are installing COM servers than plain old files.

How do I stop removal of files during uninstallation using Wix

When uninstalling my application, I'd like to configure the Wix setup to NOT to remove few files that were added as part of the installation. It seems like the uninstaller removes all the files that were originally installed from the MSI file. How do I do that?
Here are my files which I wish to keep it forever
<Binary Id="RootCABinary" SourceFile="Assets\Certificates\RootCA.cer" />
<Binary Id="SubCABinary" SourceFile="Assets\Certificates\SubCA.cer" />
I have used WixIIsExtension.dll to install these certificates to the windows store.
Overwrite: Is it important that the file never gets overwritten? If so, add
"Never Overwrite" to your component. WiX attribute: NeverOverwrite="yes". Remember to test upgrade scenarios!
Permanent Component: As stated by Pavel, you can set a component permanent:
<Component Permanent="yes">
<File Source="License.rtf" />
</Component>
Blank GUID: Another way to do it is to set a blank component GUID. It essentially means "install and then leave alone". No repair or uninstall should be done (remember to add NeverOverwrite="yes" if the file should never be overwritten):
<Component Guid="" Feature="MainApplication">
<File Source="SubCA.cer" KeyPath="yes" />
</Component>
Read-Only Copy: I sometimes install files to a per-machine path (for example somewhere under program files) and then copy them to a per-user location (somewhere in the user-profile) on application launch, and then do operations on them that entail that the files should not be deleted. This is good in cases where you want to do something that change the files in question (they need to be writable). Then it is good to "untangle" them from deployment concerns (files will not be meddled with by installer operations at all - the installer has no knowledge of them). The original read-only copy installed to program files can be uninstalled though (no longer needed?).
Other approaches: You can also create such files using custom actions during installation (usually text files only), you can download the file in question from your web site on application launch (makes the file easy to manage and update / replace? Vulnerable to connection problems - firewalls, etc...) and the application can create the file using "internal defaults" in the main executable on launch. And there are no doubt further approaches that I can't recall.
Put your binaries in a separate WiX component and make it permanent. Have a look at this thread as well

Wix component GUID "*" is not valid for this component

I'm trying to solve my issue with autogerating GUID for multiple components in same folder installed under AppData (per-user installation).
Before edit I had one component with 3 files. Then I've decided to use auto GUID for this component, so I have divided it into 3 component (each with one file). I thought that now I can use Component GUID with * and registry value with KeyPath=yes but it's not working. Any advice is very appreciated.
Here is code snippet:
<Directory Id='INSTALLDIR' Name='$(var.myInstallDir)'>
<Component Id='MainExecutable' Guid='I_WOULD_LIKE_ASTERISK_HERE_ALSO_BUT_HAVE_HARD_CODED_GUID' >
<RemoveFolder Id='RemoveINSTALLDIR' Directory='INSTALLDIR' On='uninstall' />
<util:RemoveFolderEx On="uninstall" Property="APPLICATIONFOLDER" />
<RegistryValue Root='HKCU' Key='Software\[Manufacturer]\[ProductName]' Type='string' Name='Path' Value='[INSTALLDIR]' KeyPath='yes'/>
<File Id='ffile1' Name='file1' DiskId='1' Source='file1'> </File>
<Shortcut Id="startmenujfile" Directory="ProgramMenuDir" Name='$(var.myAppName)'
Target="[SystemFolder]cmd.exe" Arguments=" /c START javaw.exe -jar [INSTALLDIR]file1.jar ."
WorkingDirectory="INSTALLDIR"
Icon="apsoiconmultiico" IconIndex="0" />
<Shortcut Id="desktopjfile" Directory="DesktopFolder" Name='$(var.myAppName)'
Target="[INSTALLDIR]file1.jar" Arguments=" ."
WorkingDirectory="INSTALLDIR"
Icon="iconmultiico" IconIndex="0" />
</Component>
<Component Id='MainExecutable2' >
<File Id='ffile2' Name='file2' DiskId='1' Source='file2' />
<RegistryValue Root='HKCU' Key='Software\[Manufacturer]\[ProductName]' Type='string' Value='' KeyPath='yes'/>
</Component>
<Component Id='MainExecutable3' >
<File Id='ffile3' Name='file3' DiskId='1' Source='file3' />
<RegistryValue Root='HKCU' Key='Software\[Manufacturer]\[ProductName]' Type='string' Value='' KeyPath='yes'/>
</Component>
</Directory>
And error for components:
error CNDL0230 : The Component/#Guid attribute's value '*' is not valid for this component because it does not meet the criteria for having an automatically generated guid. Components with registry keypaths and files cannot use an automatically generated guid. Create multiple components, each with one file and/or one registry value keypath, to use automatically generated guids.
Thank you
EDIT:
Thanks to #Stein Åsmul answer. I need to ask one more time..
I'm trying to solve this because we are moving from Java Web Start (jnlp) to very simple .msi file which installs only elementary files and shortcuts. Then the app itself has automatical update system which downloads all other files.
Our app can have "mupliple sets of versions" installed on same machine (like set A: "app 1 demo, app 2 test" and set B: "app 2 demo, app 2 test"). Every set and every version in the set can have different files (this is a job for update system itself).
Now the question. I'm a newbie in .msi installation so I'm not sure about many steps. I know productId, upgradecode.. but what about component GUID (in my case Component Id='MainExecutable') in enviroment with multiple sets of app installed on same machine (per-user but different directory - AppData/local/setA and AppData/local/setB) with registry KeyPath=yes? Can this component has fixed GUID for all our installations if productId is different (so hardcoded in .wxs for all installations)? Thank you for explanation.
Short Answer: You cannot use auto-guids for components that have the same / non-unique key path - which is the case for per-user registry key paths. Simpler approach: Install files to a per-machine location and copy them into each user-profile on application launch instead of
installing them per-user via an MSI. This de-couples all user-profile files
from common deployment problems (overwriting / resetting, upgrade problems, uninstall problems, etc...). Auto-Guids are possible for per-machine key paths - they are unique per component.
Per-User Key Path: HKCU\Software\Company\Product\MyKeyPath
Repeats for every user! => No auto-guid possible. It is not unique.
User 1: C:\Profiles\User1\Product\File.exe, Key path: HKCU\Software\Product\MyKeyPath
User 2: C:\Profiles\User2\Product\File.exe, Key path: HKCU\Software\Product\MyKeyPath
For the record, here is what would happen if you set a userprofile disk-based key-path (as opposed to a registry key path which you are supposed to use): Color illustration.
Per-Machine Key Path: C:\Program Files\Company\Product\Main.exe
Only one installation instance! Unique key path allows auto-guid.
Read-Only Templates: A general issue first: it is recommended that you don't install files directly into the user profile folders. Rather you should install them to your main installation folder under Program Files and then copy them in place during application launch for every user who uses the application. The files can then be copied to every user-profile on demand and on launch of the application (upgrades are possible too, if you implement it well).
Technically: You cannot use an auto-guid for components that has the same / non-unique key path. The technical reasons can perhaps be best understood by reading this old answer: Change my component GUID in wix? Essentially the key path must be unique in order to be able to create an automatic GUID, and this is not the case with per-user registry keys. The path is the same for all users - to the same registry key (even if the content is different for each user). A limitation of the MSI technology.
Note that if you install to a per-machine path you will be able to use auto-GUIDs since you can have a unique file key path for the component. This should work fine. Just move the files to a per-machine path and set an auto-guid. Upgraded files will overwrite older files and you can copy newer files over the ones in the user profile on launch - if desirable. A risky operation most of the time.
Cloud: I am fond of cloud-based approaches to download files into the user profile on-demand directly from the Internet or Intranet as an alternative to deployment via MSI. It all depends what you have access to.
More Details: There are too many pre-existing answers that revolve around the same points for there to be any value in rewriting it. Please check the below links for more details on the deployment of per-user files with MSI:
Create folder and file on Current user profile, from Admin Profile
Wix deferred custom action access denied
How to create nested folder in AppData
Create a .config folder in the user folder
Make WIX installer place files in AppData

WiX MajorUpgrade of Windows Service, preserving .config, and avoiding a reboot

I am struggling to get MajorUpgrade, ServiceControl, .config files to work nicely together. After my other question, I'm now kinda having the opposite problem again.
Before, the files weren't being overwritten because the AssemblyFileVersions were static so I fixed that. 1) Now, even with Schedule="afterInstallExecute" my KeyPath='yes' .config file is still being overwritten even though the existing file modified date is different than the file creation date and it is set as a KeyPath. I'm currently having to overwrite the .config file and restart the service after the install.
2) And even if I fix that, I still have a problem of avoiding a reboot. If I say Schedule="afterInstallInitialize" then I believe the .config file will certainly be removed along with the service too early. If I say Schedule="afterInstallExecute" then the service isn't stopped and after the install a reboot is necessary. (That's right, right?) Stopping the service manually prior to the install let's me avoid the reboot. Adding a net stop custom action could work to replace the ServiceControl I guess, but getting all the conditions right seems complex.
3) As a bonus, I'd like to NOT remove the service at all during an upgrade. Can I just stop the service, replace the binary, and start the service again? That will avoid re-entering the service account credentials for an upgrade. But of course it still needs to install on a first install and uninstall on a feature removal.
Here's the meat of it (which is also bundled later, in case that somehow matters):
<MajorUpgrade DowngradeErrorMessage="A newer version is already installed."
Schedule="afterInstallExecute" />
<ComponentGroup Id="ServiceCG">
<Component Id="Service" Guid='*' Win64='yes' Directory='INSTALLDIR'>
<File Id='ServiceEXE' Source='$(var.root)Service.exe' />
<ServiceInstall Id="ServiceInstall"
Name="MyService"
DisplayName="My Server"
Type="ownProcess"
Start="auto"
ErrorControl="normal"
Description="My Server Service"
Interactive="no"
Account="[...]"
Password="[...]" />
<ServiceControl Id="StopService" Name="MyService" Start="install"
Stop="uninstall" Wait="yes" Remove="both" />
<util:User Id="UpdateServiceAccountLogonAsService" UpdateIfExists="yes"
CreateUser="no" Name="[SERVICEACCOUNTFULL]"
LogonAsService="yes"/>
</Component>
<Component Id="ServiceConfig" Guid='*' Win64='yes' Directory='INSTALLDIR'>
<File Id='FileServiceConfig' KeyPath='yes'
Source='$(var.root)Service.exe.config' />
</Component>
</ComponentGroup>
Related but unanswered:
Prevent service removal/install during WiX major upgrade - service not stopping
WiX version 3.8.1128.0
EDIT: it seems this explanation of the same issue, or on the same topic at least, might be easier to understand: Msiexec: automatic rollback to previous version on installation failure
You are banging your head against several core MSI usage problems here.
File versioning: during installation the default file overwrite mode (defined by the REINSTALLMODE property) won't replace files that are equal version by default. This can be changed by setting REINSTALLMODE = "emus". This will replace files with equal version for versioned files. Unversioned files will be preserved if modify and create dates are different.
Upgrade behavior: like Chris says, files that appear to be reverted to default are actually uninstalled and reinstalled due to major upgrade configuration. File preservation is only possible in major upgrades if RemoveExistingProducts is placed late in the InstallExecuteSequence. Then shared files between releases are never uninstalled and the file versioning rules described in point 1 apply for overwriting.
Service configuration preservation: avoiding re-entry of service credential information is a common problem for major upgrades that uninstall early in the InstallExecuteSequence. In other words the product is uninstalled and then reinstalled wiping out changed files. I don't recommend it, but some people argue for this solution: How to only stop and not uninstall windows services when major upgrade in wix? (Rob Mensching is the WIX and Orca author - I think he is suggesting this solution as an option, and not necessarily a recommendation. Please ask in the linked post to be sure). With correct component referencing and uninstall placed late in the InstallExecuteSequence this problem is normally avoided altogether, and this is then a preferred approach (normal component referencing prevent the component from uninstalling altogether leaving service settings and changed config files intact - if, and only if, component referencing is correct - see description of this concept below). However, my preferred approach is still to use a separate MSI for the service install and configuration if you are using a user account to run the service - then it is a self contained deployment unit and can be included in a bootstrapper and updated on its own, and best of all: it is undisturbed by any other application changes or hotfixes. Finally I would like to point out that a service running with a user account isn't a recommended approach to begin with - for security and deployment reasons alike.
Component referencing: refers to the GUIDs assigned to MSI components and how they must match one, and only one (absolute) path at all times through all upgrades. See a better discussion of this with a couple of examples here: Change my component GUID in wix?
I didn't mention the option of setting the MSI components installing services to permanent to prevent their removal on uninstall for the simple reason that this isn't good practice at all. Then files and registration will remain on final uninstall, and you need a custom action to clean up. Very bad practice and bound to cause lots of extra work and problems with dangling component references.
The file create/mod rule only applies to install/reinstall a component. It doesn't prevent the component from being uninstalled. Your major upgrade is scheduled very early which means the previous version is completely uninstalled and then then the new version is installed. This is why your file is overwriting when you don't expect it to. Schedule RemoveExistingProducts later to avoid this problem.
Set your Stop attribute to both install and uninstall. Those two changes should solve your problems.

How to remove log folder when uninstalling?

I have WCF in IIS. WCF uses log4net logs. How I can remove log folder on uninstall?
The log folder is in target folder.
I use this piece of code:
<Directory Id='Logs' Name='Logs'>
<Component Id="comp_iislogs" Guid="{0B0E2F6E-008D-42C9-8A7C-1F1265C077A1}"
SharedDllRefCount="no" KeyPath="no" NeverOverwrite="no" Permanent="no" Transitive="no"
Win64="no" Location="either">
<RemoveFile Id="Files" On="uninstall" Name="*.log"></RemoveFile>
<CreateFolder/>
</Component>
</Directory>
The problem is log file is in use on uninstallation and uninstaller says please stop app etc...
You'll have to kill the process that has the logfile open then! If that's something in a web app then you'll probably only have to recycle the application pool for the handle to be released (I think).
You can do that using appcmd recycle apppool /apppool.name: <pool name> from within your WiX scripts. You might want to actually stop then restart site however just to avoid any chances of it being open at the time.
MSI removes only files it copied during initial installation.
Logs generated by the application are not recognized by the uninstall process.
In other words, if at least one file exists in a directory to be removed, MSI will treat it as user file and skip its parent directory from removal.
In order to remove log directory you need to forcefully delete its contents first, but I would advise against that as you may encounter locking issues you don't want to deal with.
Use RemoveFolderEx element from Util extension in WiX.
With this approach, all the subdirectories and files are removed.
Example:
<util:RemoveFolderEx On="uninstall" Property="Logs" />
Place this inside the Component tag.