I have been attempting to create an installer using WIX (3.10.1.2213).
I am installing a Windows Service that uses DCOM.
I have a component that uses ServiceInstall and ServiceControl to do what I require.
However I am having issues when it comes to the AppId entries.
If I use the following...
<AppId Id="{REALGUID}" Advertise="no" Description="MyDescription" LocalService="MyService" ServiceParameters="-Service" />
...My installation fails when attempting to start the service - with the ever helpful "...failed to start. Verify that you have sufficient privileges to start system services".
However, if I add the registry entries manually - outside of WIX (even by exporting the entries that WIX creates - so they are definitely the same) - the installation succeeds.
Does anyone know what could be happening here?
In summary, WIX creates the entries I expect, but installation fails.
If I export these entries and start from scratch, merge the entries into the registry and rerun the installer, it succeeds.
I have attempted to move the AppId entry to other locations in the wxs file. I have also attempted to manually set the registry entries using <RegistryValue...>, but it appears to have the same result (I see the entries get created, but the service fails to start).
I'm not sure if this is relevant, but this service requires another entry under HKCR\AppID\{GUID} which I do create using <RegistryValue...>. I'm not sure if that is somehow causing a conflict and I can't currently debug the service as it doesn't get far enough.
Also, from here, I see...
If this element is nested under a Fragment, Module, or Product
element, it must be advertised.
But I don't fully understand it. Does it mean if 'directly' nested under...?
Or could this be my problem and my wxs file could be ordered badly, because I need registry entries instead of being Advertised?
It is currently something like this...
<Fragment>
<Directory...>
<Component...>
<File...>
<AppId...>
<RegistryValue...>
<ServiceInstall...>
<ServiceControl...>
I am very confused - but hopefully missing something obvious.
Hopefully someone can shed some light on it for me.
Regards,
Ads.
If it helps, here is an edited extract of the component in question...
<Component Id="ServiceControl" Guid='REALGUID' >
<File Id="MyApplication.exe" Name="MyApplication.exe" KeyPath="yes" Vital="yes" Source="$(var.MyApplication.TargetDir)\MyApplication.exe" />
<AppId Id="{REALGUID}" Advertise="no" Description="MyApplication" LocalService="MyApplication" ServiceParameters="-Service" />
<RegistryValue Root="HKCR" Key="AppID\{REALGUID}" Name="Group" Value="[GROUP]" Type="string" Action="write" />
<ServiceInstall
Id="ServiceInstaller"
Type="ownProcess"
Name="MyApplication"
DisplayName="My Application"
Description="Some Description"
Start="auto"
Account="LocalSystem"
Interactive="yes"
ErrorControl="normal"
Vital="yes" >
<ServiceDependency Id="[FTPSERVICE]" />
</ServiceInstall>
<ServiceControl Id="MyApplication" Name="MyApplication" Start="install" Stop="uninstall" Remove="uninstall" Wait="yes" />
</Component>
Related
I've written a new installer using the WiX Toolset. It appears that the best practice is to use the heat.exe application to run through your built application files and auto-generate references for inclusion in your installer. This is great and all, but I find that by using this technique you pretty much block those files from being usefully in ANYTHING else except the act of copying them to the install directory. This is because I can't seem to "reference" these files for other things. For example. One of the files I would like to install as a service, but the ServiceInstall mechanism doesn't seem to let you use something referenced out of the harvest. Also, one of my files is an XML file that I would like to modify based on input from the user during install. Again, I can't seem to reference this file out of the harvest for use in the XmlConfig mechanism.
I've seen this post, but the chosen answer doesn't actually provide an example. And to boot, the WiX compiler does not let you put '#' symbols in the identifier field because it is "not a legal identifier" as the answer post claims. And if you use the plain IDs out of the harvest, it complains that they already exist.
Here is a snippet out my harvest .wxs file.
<!-- Xml file I'd like to modify during install -->
<Component Id="cmp78CF3591818BB6F883096F2C98654BA9" Guid="*">
<File Id="fil1532F0BC6EDCE81B25489D872A72339A" KeyPath="yes" Source="$(var.MyApplication.TargetDir)\log.config" />
</Component>
<!-- ... -->
<!-- Application I'd like to install as a service -->
<Component Id="cmp84F0EA671F93094E33AE84FA2A03BA2E" Guid="*">
<File Id="filD4A27A27D20D3D734B279B4F21754836" KeyPath="yes" Source="$(var.MyApplication.TargetDir)\MyService.exe" />
</Component>
For the service install, I feel like the intuitive way would be something like this:
<Component Id="cmp84F0EA671F93094E33AE84FA2A03BA2E">
<File Id="filD4A27A27D20D3D734B279B4F21754836" />
<ServiceInstall
Id="MyServiceID"
Name="MyService"
Type="ownProcess"
Start="auto"
ErrorControl="normal"
Interactive="no">
</ServiceInstall>
<ServiceControl Name="MyService" Id="MyServiceControl" Start="install" Stop="both" Remove="uninstall" Wait="yes"/>
</Component>
But of course this does not work because it claims the IDs are duplicated. Which I guess they are, but how can I say "You know that file 'X' inside the harvest... ya, I'd like to install that as a service." I have been able to get the install to work, but I had to filter MyService.exe out of the harvest and manually added it. Now if that is the case every time you'd actually like to do something with a particular file, then I think I may just forgot using the stupid heat.exe technique and manually input every file. So what exactly is the syntax that you would use to reference files from inside the heat.exe harvest?
Simplest answer: Don't use Heat.exe to generate authoring for files that require special handling, like services. Exclude those files from harvesting (using a staging directory if necessary).
Heat has generated component definitions for you. Put the ServiceInstall element inside the component in harvest.wxs. Your new snippet would look like this:
<!-- Application I'd like to install as a service -->
<Component Id="cmp84F0EA671F93094E33AE84FA2A03BA2E" Guid="*">
<File Id="filD4A27A27D20D3D734B279B4F21754836" KeyPath="yes" Source="$(var.MyApplication.TargetDir)\MyService.exe" />
<ServiceInstall
Id="MyServiceID"
Name="MyService"
Type="ownProcess"
Start="auto"
ErrorControl="normal"
Interactive="no">
</ServiceInstall>
<ServiceControl Name="MyService" Id="MyServiceControl" Start="install" Stop="both" Remove="uninstall" Wait="yes"/>
</Component>
I have a project that includes an ATL service. Currently, our installer registers the service with custom actions that run the installed service executable with the command:
MyService.exe /server
and unregisters it with the command
MyService.exe /unregservice
This has caused headaches in some situations where the command has failed and the installation becomes stuck in a state where it can neither be completed or fully rolled back, leaving the application unusable.
We would like to replace these custom actions by using the ServiceInstall tag to do the registration completely within the MSI file, but we can't get it to work. Our initial code looked like this:
<Component Id="c.MyService.exe" Guid="{PUT-GUID-HERE}">
<File Id="f.MyService.exe" Name="MyService.exe" KeyPath="yes"
DiskId="1" Source="$(var.MyService.TargetPath)" Vital="yes" />
<ServiceInstall Id="svci.MyService" Name="MyService" Type="ownProcess"
Start="demand" ErrorControl="normal" DisplayName="MyService"
Description="My Service" Account="LocalSystem" Interactive="no"
Vital="yes">
<ServiceDependency Id="RPCSS"/>
</ServiceInstall>
<ServiceControl Id="svcc.MyService" Stop="both" Remove="uninstall"
Name="MyService" Wait="yes" />
</Component>
The install would complete, but running the program failed with this message:
Retrieving the COM class factory for component with CLSID {...} failed due to the following error: 80040152 Class not registered (Exception from HRESULT: 0x80040154 (REGDB_E_CLASSNOTREG))
One suggestion found via google was to add in the AppId tag inside the Component tag as follows:
<Component ... />
...
<AppId Id="$(var.MyServiceGUID)" LocalService="MyService" Description="MyService" />
...
</Component>
However this didn't have any effect.
Any ideas how to replicate the ATL's self-registration in the MSI itself?
For reference, I believe I am having the same problem as in this ancient, unanswered post: http://social.msdn.microsoft.com/Forums/vstudio/en-US/eb33cf47-628a-4fbf-a740-f81afe2f2b43/atl-service-install-and-registration-issue-com-server-vs-windows-service?forum=vcgeneral
Thanks very much
WiX has a program called Heat that can be used to harvest the COM metadata for your ATL server. Run this program to generate a wxs fragement, migrate the COM elements to your wxs fragement then rebuild and test on a clean snapshotted VM. Rinse and repeat if needed as COM/ATL is a little tricky at times.
Harvest Tool (Heat)
I build a perMachine installer using WiX 3.6 to install a software I had not developed. Unfortunately the software creates some registry keys under HKCU during execution.
On uninstall, the self created keys should also be removed. It seems not so easy to remove these keys. I am "fighting" with ICE57 and/or ICE38. Both complaining the mix between perUser and perMachine data.
Hopefully you can point me in the right direction on fixing this issue.
To overcome ICEs you should move Per-User registry to separate components and use some registry entry as keyPath for that component, i.e.:
<Component Id='PerUserRegistry' Guid='*'>
<RegistryValue Id="PerUserRegistry_KeyPAth" KeyPath="yes" Root="HKCU" Key="Software\[Manufacturer]\[ProductName]\[ProductCode]\PerUserRegistry" Name="[PackageCode]" Value="[ProductVersion]" Type="string" />
<!--Other Per-user registry goes here-->
</Component>
I completely agree with Christopher: It is common practice to leave per-user data on uninstall, but if removal is necessary, then Active Setup is the only real option.
First I propose you to remove them on Install or Re-Install instead of uninstall, you just need add RemoveRegirty entry and Active Setup, i.e. with this WiX code:
<Component Id='ActiveSetup' Guid='*'>
<RegistryValue Id="ActiveSetup00" Root="HKLM" KeyPath="yes" Key="SOFTWARE\SOFTWARE\Microsoft\Active Setup\Installed Components\[PackageCode]\" Name="StubPath" Value="msiexec /fup [ProductCode] /qb-!" Type="string" />
<RegistryValue Id="ActiveSetup01" Root="HKLM" Key="SOFTWARE\SOFTWARE\Microsoft\Active Setup\Installed Components\[PackageCode]\" Value="[ProductName] [ProductVerion] Configuration" Type="string" />
</Component>
<Component Id='PerUserRegistryCleanup' Guid='*'>
<RegistryValue Id="PerUserRegistry_KeyPath" Root="HKCU" KeyPath="yes" Key="SOFTWARE\SOFTWARE\Microsoft\Active Setup\Installed Components\[PackageCode]\" Name="StubPath" Value="msiexec /fup [ProductCode] /qb-!" Type="string" />
<RemoveRegistryKey Id='PerUserRegCleanup' Root='HKCU' Action='removeOnInstall' Key='Key\To\Be\Removed'/>
</Component>
Note: [PackageCode] use in ActiveSetup is very recommended, so with each new version (build) of MSI package you add separate entry (also see my final note). I used per-user active setup registry as key-path on purpose, so you don't run it for current user twice.
As for removing them after uninstall,
Now, hopefully you need to remove entire key, and not just some values. In either case, I would create custom action to add Registry entry for Active Setup during uninstall (or if there are many such keys/values, create and deploy .CMD file with those and launch it on uninstall, before RemoveFiles action, to add all of them to registry).
Note: that I would strongly recommend adding deleting this registry during install, or you might end up removing per-user values when software is yet installed.
So here's WiX code for all of this:
<CustomAction Id="CA_UninstallRegistryCleanUp" Directory="SystemFolder" ExeCommand="REG.exe ADD "HKLM\SOFTWARE\Microsoft\Active Setup\Installed Components\MySoftName_CleanUp" /v StubPath /d "reg add ^"HKCU\Key\To\Be\Removed^" /va /f" /f" Return="ignore" />
<InstallExecuteSequence>
<Custom Action='CA_UninstallRegistryCleanUp' After='RemoveRegistryValues'>REMOVE~="ALL"</Custom>
</InstallExecuteSequence>
<Component Id='RegCleanup_Remover' Guid='*'>
<RegistryValue Id="PerUserRegistry_KeyPAth" Root="HKLM" KeyPath="yes" Key="SOFTWARE\[Manufacturer]\[ProductName]\[ProductCode]\" Name="DummyKey" Value="[ProductVersion]" Type="string" />
<RemoveRegistryKey Id='RegCleanup_Remover' Root='HKLM' Action='removeOnInstall' Key='SOFTWARE\Microsoft\Active Setup\Installed Components\MySoftName_CleanUp'/>
</Component>
Final notes:
There just two small issues with all this Active Setup stuff: be careful on Windows Terminal Servers; and once active setup was run for one user for current .MSI, it will not run again if you decide to reinstall same package, unless you change its PackageConde or raise version under ActiveSetup registry key. These are topics for another day, let me know if need them clarified.
And don't forget to add all of above Components to some Feature.
The Windows Installer considers this user data and best practice is to not remove it. Either way, it's very difficult to try to remove it anyways since other user profiles are out of scope / context. It's theoretically possible to write a custom action to enumerate profiles and load registry hives but on some versions of Windows ( Vista ) that won't work due to restricted permissions granted to the windows installer service.
If you really, really must be able to remove custom action data on uninstall then take a look at:
Active Setup Explained
You are going to need to leave behind an program (exe for example ) by marking a component as permanent. Then you'll need a custom action to write a registry value during the uninstall (because Windows Installer doesn't support this).
The concept is during the install you lay down an EXE and during the uninstall you leave you. You then write to the ActiveSetup registry key telling it to run your EXE once for each subsequent user to logon to the machine. The EXE then deletes your registry values. Reboot (politely) if needed to unload the extensions from explorer.
But honestly, a better designed application wouldn't need all of this.
I have my service installed on the machine by an msi package(WIX). But when an major upgrade is done,service gets uninstalled but it doesnt get installed.
This is my code:
<Component Id="abc" Guid="{E64A8CDD-816F-4544-9ACD-A2E367F7758A}">
<File Id="EventTraceService.exe" Source="..\..\..\..\Products\abc.exe" Vital="yes" KeyPath ="yes"/>
<File Source="..\..\..\..\Products\abc.exe.config" Vital="yes" />
<ServiceInstall
Id="ServiceInstaller"
Type="ownProcess"
Vital="yes"
Name="abc"
DisplayName="abc"
Description="Monitoring and management of Trace"
Start="auto"
Account="LocalSystem"
Interactive="yes"
ErrorControl="normal"
/>
<ServiceControl Id="StartService" Start="install" Stop="uninstall" Remove="uninstall" Name="abc" Wait="yes" />
Thanks in advance!
One possible explanation is that you changed the GUID of the component. As a result, (the different versions of) the same resources are being managed by different components.
From the windows installer documentation about what happens when the component rules are broken:
An author includes the same resource in two different components.
If two components have a resource under the same name and location and both components are installed into the same folder, then the removal of either component removes the common resource, which damages the remaining component.
Uninstalling either component removes the resource and breaks the other component.
The component reference-counting mechanism is damaged.
This seems to match your symptom.
If the service EXE has the same version in both packages, this happens because of the file versioning rules. Here is an article with more details: http://setupanddeployment.com/windows-installer-bugs/missing-files-upgrade/
During Installation, I'm installing my service using ServiceInstall and ServiceControl tags. But, my service is not running. I'm getting error message "Please check you have sufficient privilege to start service". But, I'm in Administrators group. I'm using Wix ver 3.0.
code snippet is here,
<File Id='myexe' Name='myexe.exe' DiskId='1'
Source='myexe.exe' Vital='yes'>
</File>
<ServiceInstall Id='myService' DisplayName='MySampleService'
Name='MySampleService'
ErrorControl='normal' Start='auto'
Type='ownProcess' Vital='yes' />
<ServiceControl Id="StartService"
Name="MySampleService" Start="install" Wait="yes" />
<ServiceControl Id="StopService" Name="MySampleService"
Stop="both" Wait="yes" Remove="uninstall" />
Please help me.
That is the generic error you get when the service fails to install or start (if you are telling it to do that) for any reason. It is very frustrating. The only way to debug is slowly remove dependencies until things finally work. More often than not, the service requires some code (an assembly in the GAC?) that isn't fully configured until later.
I usually debug by looking at the Services.msc and trying to start the service while the error message is up. That typically provides better error messages than the Windows Installer does.
do not try to start .NET Services depending on Components being installed into the Global Assembly Cache GAC, ServiceStart comes too early for that
You could also examine Window Eventlog to identify the problem. If the problem is a missing binary the you can use Depends to find out what is missing.
Try to use util:User element
for example:
<util:User Id="myServiceUser" Name="[USERNAME]" LogonAsService="yes" UpdateIfExists="yes" CreateUser="no"
FailIfExists="no" />