WIX: Install Services using runner and multible dlls - service

I'm working on a Wix installer which should install multiple Services based on the same runner. This a some dlls which will be loaded by the runner. With sc.exe this works fine on my test system. Now my question, can I use standard Wix ServiceInstall for this? I have only one runner.exe and I'm not sure how to write this in the XML. Or would a Custom Action be the right way?
Thanks!!

The ServiceInstall and ServiceControl elements don't come after the file element per say but they are children on the Component element. They target the keypath of the component which happens to be the File element. You can easily have multiple services defined in a single component pointing to the same executable.
<Component Id="c1" Guid="dbc1b8dd-14e1-380f-5793-4a746fa0c5c5">
<File Id="f1" Source="$(var.SourceDir)\TestService.exe" KeyPath="yes" />
<ServiceInstall Id="si1" Name="TestService1" DisplayName="TestService1 Service" Description="TestService1 Service" ErrorControl="normal" Start="auto" Type="ownProcess" />
<ServiceControl Id="sc1" Name="TestService1" Start="install" Stop="both" Remove="both" Wait="yes" />
<ServiceInstall Id="si2" Name="TestService2" DisplayName="TestService2 Service" Description="TestService Service" ErrorControl="normal" Start="auto" Type="ownProcess" />
<ServiceControl Id="sc2" Name="TestService2" Start="install" Stop="both" Remove="both" Wait="yes" />
</Component>
To have each service behave differently you'll have to write code in your service to access ServiceBase.ServiceName (this.ServiceName in the OnStart method likely). From here you can dynamically load different classes from different assemblies.

Related

Azure Service Fabric - Configure service instance parameters using Powershell

Is it possible to inject parameters at run time into a Guest Executable via the Settings.xml file or another means? I have a GuestExecutable which I need to pass some configuration to it - a URL at service creation time.
I need two instances of the service running with different parameters, the service instance information has to differ in terms of a custom parameter I need to pass through . Is this possible using Powershell or, do I need to version the config and create a new version?
Thanks in advance
Have you tried the following command: New-ServiceFabricApplication ?
When you create your application manifest file, the parameters will contain replaceable parameters that you set when you register a new application.
An ApplicationManifest.xml example like this:
<?xml version="1.0" encoding="utf-8"?>
<ApplicationManifest ApplicationTypeName="MyAppTypeName" ApplicationTypeVersion="1.0.0" xmlns=...>
<Parameters>
<Parameter Name="Web1_InstanceCount" Value="-1" />
<Parameter Name="ENVIRONMENT_NAME" Value="DEV" />
<Parameter Name="FEPlacementConstraints" Value="NodeTypeName==FrontEnd" />
</Parameters>
<ServiceManifestImport>
<ServiceManifestRef ServiceManifestName="MyServicePkg" ServiceManifestVersion="1.0.0" />
<ConfigOverrides />
<EnvironmentOverrides />
</ServiceManifestImport>
<DefaultServices>
<Service Name="Web1">
<StatelessService ServiceTypeName="MyServiceType" InstanceCount="[Web1_InstanceCount]">
<SingletonPartition />
<PlacementConstraints>[FEPlacementConstraints]</PlacementConstraints>
</StatelessService>
</Service>
</DefaultServices>
</ApplicationManifest>
You would change the settings file using config overrides like this:
<ConfigOverrides>
<ConfigOverride Name="Config">
<Settings>
<Section Name="MyConfigSection">
<Parameter Name="MySetting" Value="[ENVIRONMENT_NAME]"/>
</Section>
</Settings>
</ConfigOverride>
</ConfigOverrides>
Or you could set environment variables on your service like this:
<EnvironmentOverrides CodePackageRef="Code">
<EnvironmentVariable Name="ASPNETCORE_ENVIRONMENT" Value="[ENVIRONMENT_NAME]" />
</EnvironmentOverrides>
In my opinion the environment overrides would work better on your case,
because most guest executable are not flexible on how you can configure them but generally they accept environment variables.
Then you:
Upload your application with: Copy-ServiceFabricApplicationPackage
Register your application with Register-ServiceFabricApplicationType
And then you register each new app with the settings you need:
.
New-ServiceFabricApplication -ApplicationName fabric:/myapp/todolist-dev -ApplicationTypeName "MyAppTypeName" -ApplicationTypeVersion "1.0.0" -ApplicationParameter #{Web1_InstanceCount='-1'; ENVIRONMENT_NAME='DEV'}
New-ServiceFabricApplication -ApplicationName fabric:/myapp/todolist-uat -ApplicationTypeName "MyAppTypeName" -ApplicationTypeVersion "1.0.0" -ApplicationParameter #{Web1_InstanceCount='-1'; ENVIRONMENT_NAME='UAT'}
The only down side of this approach is that you would end up with two applications, but don't think would be a problem for you, they will be managed mostly the same way as you would do with a single application.
if you strictly need to run both together on same application, you could do some workarounds:
Using multiple Config packages(don't think would work well with guest executables, but works well with reliable services
Using the startup script, where you would add the logic to pass the parameter to your startup exe, something like the following:
In your ServiceManifest.xml:
<CodePackage Name="Code" Version="1.0.0">
<EntryPoint>
<ExeHost>
<Program>start.bat</Program>
<WorkingFolder>CodePackage</WorkingFolder>
</ExeHost>
</EntryPoint>
</CodePackage>
On the same folder (code) of your .exe, you create the start.bat file with following contents:
myApp.exe %EnvironmentVariableNameSetBySF%

Major Upgrade without uninstallation of Windows Service

I am really very sorry for being redundant. I have checked a lot of other posts in this site itself and perhaps some other sites. I am not able to get Major Upgrade working without uninstalling & reinstalling of service. I am changing the Product Code and Version and the UpgradeFileComponent is the component that is part of the Upgrade. All the remaining are the same as in 1.0.0. I am doing a POC and hence would like to make only this small change (not as a patch, but as a major upgrade). Following is my Product.wxs. I am not including the markup for the other things like ServiceAccountDlg, Variables.wxi or en-us.wxl, since it may make it really long. Can anyone please help me? I have already tried WIX_UPGRADE_DETECTED, UPGRADINGPRODUCTCODE and so on, but not able to get it working. Everytime, the service is getting uninstalled and reinstalled. I am verifying this in the following way. Once the service starts, it creates a log file in ProgramData and keeps appending it to every 5 seconds. During uninstallation of the MSI, I am deleting this log file and its folder. After the service gets reinstalled and restarts, the log file gets created again. With this I am able to figure out that the service is getting reinstalled always with the major upgrade. I only want the new file to be deployed without reinstalling the service or any other component being uninstalled. I have heard from some people that the toolset checks for changed files and reinstalls them only if there is a change. But this doesn't seem to be the case. I have tried using the Schedule attribute with various values also, but no luck. Any help will be really great. I have been trying this for so many days without any luck. Please let me know if any more info is required from me.
<?xml version="1.0" encoding="UTF-8"?>
<?include Variables.wxi ?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi" xmlns:util='http://schemas.microsoft.com/wix/UtilExtension'>
<Product Id="$(var.ProductCode)" Name="$(var.ProductName)" Language="!(loc.LANG)" Version="$(var.ProductVersion)" Manufacturer=" MyCompany" UpgradeCode="$(var.UpgradeCode)">
<Package InstallerVersion="200" Compressed="yes" InstallScope="perMachine" Id="*" />
<MajorUpgrade DowngradeErrorMessage="A newer version of [ProductName] is already installed." />
<!--<Upgrade Id="$(var.UpgradeCode)">
<UpgradeVersion OnlyDetect="yes" Minimum="1.0.0" Maximum="2.0.0" IncludeMinimum="yes" IncludeMaximum="yes" Property="NEWERFOUND" />
</Upgrade>-->
<InstallExecuteSequence>
<!--<RemoveExistingProducts After="InstallExecute" />
<DeleteServices>NOT UPGRADINGPRODUCTCODE</DeleteServices>-->
<!--<InstallServices>NOT UPGRADINGPRODUCTCODE,NOT WIX_UPGRADE_DETECTED</InstallServices>-->
<DeleteServices>NOT UPGRADINGPRODUCTCODE</DeleteServices>
</InstallExecuteSequence>
<Condition Message='This application only runs on Windows 7 or higher OS versions.'>
<![CDATA[Installed OR (VersionNT64 >= 601)]]>
</Condition>
<MediaTemplate />
<Property Id="MSIFASTINSTALL" Value="1"/>
<Property Id="MsiLogging" Value="v" />
<Property Id="MSIENFORCEUPGRADECOMPONENTRULES" Value="1" />
<Property Id="INSTALLDIR">
<RegistrySearch Id='MyCompanyMSISampleRegistry' Type='raw' Root='HKLM' Key='SOFTWARE\MyCompany\CustomApp' Name='INSTALLDIR' Win64='yes' />
</Property>
<WixVariable Id="WixUILicenseRtf" Value="License.rtf" />
<Feature Id='Complete' Title='Foobar 1.0' Description='The complete package.'
Display='expand' Level='1' ConfigurableDirectory='INSTALLDIR' AllowAdvertise='no' InstallDefault='local' Absent='disallow'>
<Feature Id="FileFeature" Title="File Feature" Level="1" AllowAdvertise='no' InstallDefault='local' Absent='disallow' Display='expand'>
<ComponentRef Id="FileComponent"/>
<ComponentRef Id="UpgradeFileComponent"/>
</Feature>
<Feature Id="ServiceFeature" Title="Service Feature" Level="1" AllowAdvertise='no' InstallDefault='local' Absent='disallow' Display='expand'>
<ComponentRef Id="ServiceComponent"/>
<ComponentRef Id="deleteFolder"/>
</Feature>
<Feature Id="RegistryFeature" Title="Registry Feature" Level="1" AllowAdvertise='no' InstallDefault='local' Absent='disallow' Display='expand'>
<ComponentRef Id="RegistryComponent"/>
</Feature>
<Feature Id='Documentation' Title='Description' Description='The instruction manual.' Level='2' AllowAdvertise='no' InstallDefault='followParent' Absent='disallow'>
<ComponentRef Id='Manual' />
</Feature>
</Feature>
<!--<UIRef Id="WixUI_Mondo"/>
<UIRef Id="WixUI_ErrorProgressText" />-->
<UI Id="MyWixUI_Mondo">
<UIRef Id="WixUI_Mondo" />
<DialogRef Id="ServiceAccountDlg" />
<Publish Dialog="LicenseAgreementDlg" Control="Next" Event="NewDialog" Value="ServiceAccountDlg" Order="2">LicenseAccepted = "1"</Publish>
<Publish Dialog="SetupTypeDlg" Control="Back" Event="NewDialog" Value="ServiceAccountDlg">1</Publish>
</UI>
<UIRef Id="WixUI_ErrorProgressText" />
<Icon Id="MyCompanyBanner.ico" SourceFile="Binary\MyCompanyBanner.ico" />
</Product>
<Fragment>
<Component Id='Manual' Guid='7470A2CD-B07C-4AB4-9152-8C6AA53FA0F7' Directory='INSTALLDIR'>
<File Id='Manual' Name='Manual.pdf' DiskId='1' Source='1.0.0\Manual.pdf' KeyPath='yes'>
<Shortcut Id="startmenuManual" Directory="DesktopFolder" Name="Instruction Manual" Advertise="yes" />
</File>
</Component>
</Fragment>
<Fragment>
<Directory Id="TARGETDIR" Name="SourceDir">
<Directory Id="ProgramFilesFolder">
<Directory Id="INSTALLDIR" Name="$(var.InstallFolderName)" />
</Directory>
<Directory Id="DesktopFolder" Name="Desktop" />
<Directory Id="CommonAppDataFolder">
<Directory Id="MyCompanyTestInstallerLogs" Name="MyCompanyTestInstallerLogs">
<Component Id="deleteFolder" Guid="323549D2-90B7-4D5D-8A36-EEA0ACCCC35E">
<RemoveFile Id="deleteServiceFile" Name="MyCompanyTestWinSvcLog.txt" On="both" Directory="MyCompanyTestInstallerLogs"/>
<RemoveFolder Directory="MyCompanyTestInstallerLogs" Id="MyCompanyTestInstallerLogs" On="both"/>
</Component>
</Directory>
</Directory>
</Directory>
</Fragment>
<Fragment>
<Component Id="FileComponent" Directory="INSTALLDIR" Guid="F143BE3C-48D6-4138-B4E6-5CF44773CBA5" >
<File Id="SampleTextFile.txt" Name="Sample.txt" Source="$(var.Version)\Sample.txt" KeyPath="yes">
<Shortcut Id="startmenuSampleText" Directory="DesktopFolder" Name="MyCompany MSI Sample" WorkingDirectory='INSTALLDIR' Icon='MyCompanyBanner.ico' Advertise='yes' />
</File>
</Component>
</Fragment>
<Fragment>
<Component Id="UpgradeFileComponent" Directory="INSTALLDIR" Guid="4582597C-2CE0-451E-8B89-83BA4ABCE464">
<File Id="SampleXMLFile.xml" Name="Sample.xml" Source="$(var.Version)\Sample.xml" KeyPath="yes" />
</Component>
</Fragment>
<Fragment>
<Component Id='ServiceComponent' Directory="INSTALLDIR" Guid="AEA0E53F-3D70-4010-8592-9A01FE49344D">
<util:User Domain="[DOMAIN]" Id="svcUser" Name="[USER_NAME]" Password="[PASSWORD]" LogonAsService="yes" CreateUser="no"/>
<File Id='MyCompanyTestWinSvc' Name='MyCompanyTestWinSvc.exe' Source='Binary\MyCompanyTestWinSvc.exe' KeyPath='yes' />
<ServiceInstall Id="installMyCompanyTestWinSvc" Name="MyCompanyTestWinSvc" DisplayName="MyCompany Install Test Windows Service" Start="auto" ErrorControl="normal" Type="ownProcess" Account="[DOMAIN]\[USER_NAME]" Password="[PASSWORD]" />
<ServiceControl Id="sc_MyCompanyTestWinSvc" Name="MyCompanyTestWinSvc" Start="install" Stop="both" Remove="uninstall" Wait="yes" />
<ServiceControl Id="stopAndStartIIS" Name="IISADMIN" Start="uninstall" Stop="install" Wait="yes" />
<ServiceControl Id="stopAndStartSQL" Name="MSSQLSERVER" Start="uninstall" Stop="install" Wait="yes" />
</Component>
</Fragment>
<Fragment>
<Component Id="RegistryComponent" Directory="INSTALLDIR" Guid="8D8D93A4-09F5-4511-B291-720A7BC70529">
<RegistryValue Root='HKCU' Key='Software\[Manufacturer]\[ProductName]' Type='string' Value='' KeyPath='yes' />
</Component>
</Fragment>
</Wix>
Your MajorUpgrade does not specify where it is scheduled. As the docs say, the default is after InstallValidate and "This scheduling removes the installed product entirely before installing the upgrade product. " So your major upgrade will uninstall the older product completely, deleting the service, and then install your upgrade.
So you should start by having your major upgrade scheduled afterInstallExecute, because this will behave like an update on top of the existing installed product and the reference counting should minimize disruption to your service. This means that you must follow component rules, and increment the file versions of versioned files that need replacing.
Having said that, an upgrade is always an uninstall of the older product, so the ServiceControl in that older version will run, and Remove="both" might be the problem, deleting the service during the upgrade. So the original WiX ServiceControl matters.
Also, if the component rules haven't been followed an upgrade afterInstallValidate will work fine because it uninstalls everything then installs the new product. But if the component rules have not been followed in an upgrade afterInstallExecute the service component may be getting uninstalled (because of differing component ids), and there may well be other effects of not following the rules.
And to make it clear, you do not need a condition on delete services in your new install. I would start just by sequencing the major upgrade in a better place. Also, UPGRADINGPRODUCTCODE as a condition in your new upgrade has absolutely no effect. This property is set in the older product if it is being uninstalled with an upgrade. If you want to use this property it should be in the original product that is already installed, so if it's shipped and installed it is too late to alter that code now (without a patch and so on).
A more verbose MSI log would show more detail about what is happening and in what order, specify the string as voicewarmup.
I added this to my <InstallExecuteSequence>
<!-- http://stackoverflow.com/questions/15965539/how-to-only-stop-and-not-uninstall-windows-services-when-major-upgrade-in-wix don't change service config on upgrade -->
<DeleteServices>NOT UPGRADINGPRODUCTCODE</DeleteServices>
<InstallServices>NOT WIX_UPGRADE_DETECTED</InstallServices>
Seemed to work for me but I don't use this anymore due to changes in the product. You have to be sure you won't be changing the configuration of the service between versions since when you do change the configuration you do need to uninstall and install the services during the upgrade.
Services only get deleted on real unininstall (Rob [answerer of commented question] notes you don't need to condition around the Remove state since the install/uninstall state of the services is noted in the components)
And we only install the services on the first install.

Can WiX ignore failure of a service to start?

Using WiX 3.10.3
I have a service which has failed to start during the installation process. It is desired that this failure to start NOT cause the installation to fail and roll back.
My service config:
<ServiceInstall Id="ServiceInstall" Name="MyService" DisplayName="My Service"
Description="My Service Description" ErrorControl="ignore" Vital="yes"
Account="LOCALSYSTEM" Type="ownProcess" Start="auto" Interactive="no" />
<ServiceConfig ServiceName="MyService" DelayedAutoStart="yes" OnInstall="yes" OnReinstall ="yes" />
<ServiceControl Id="ServiceControl" Name="MyService" Start="install" Stop="both" Remove="uninstall" Wait="yes" />
I have not come across the right combination of attributes which would permit the installer to attempt to start the service but ignore the result. Is this possible?

Migrating WCF as Azure worker role

I have a WCF Service Library which is run as a windows service. I would like to migrate this service as Azure worker role. When I right click on a WCF project, I typically see the option "Add Windows Azure Deployment Project". With my WCF library, I do not see this option. In that case, how do I migrate the WCF service library to Azure as worker role? Any help would be greatly appreciated.
Below is the app.config for my WCF service library.
<?xml version="1.0"?>
<configuration>
<system.serviceModel>
<bindings>
<netTcpBinding>
<binding name="NetTcpBinding_IHealthService" closeTimeout="00:01:00"
openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00"
transactionFlow="false" transferMode="Buffered" transactionProtocol="OleTransactions"
hostNameComparisonMode="StrongWildcard" listenBacklog="10"
maxBufferPoolSize="524288" maxBufferSize="65536" maxConnections="10"
maxReceivedMessageSize="65536">
<readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384"
maxBytesPerRead="4096" maxNameTableCharCount="16384" />
<reliableSession ordered="true" inactivityTimeout="00:10:00"
enabled="false" />
<security mode="None">
<transport clientCredentialType="Windows" protectionLevel="EncryptAndSign" />
<message clientCredentialType="Windows" algorithmSuite="Default" />
</security>
</binding>
</netTcpBinding>
</bindings>
<client>
<endpoint address="net.tcp://localhost:9017/monitor/health/service.svc"
binding="netTcpBinding" bindingConfiguration="NetTcpBinding_IHealthService"
contract="HealthService.IHealthService" name="NetTcpBinding_IHealthService" />
</client>
</system.serviceModel>
<startup><supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0"/></startup>
</configuration>
In this case, I would like to suggest you to manually create a worker role project, add a reference to the service library project, and then host the service inside the worker role. The service host code is similar to what you get for a normal console/Windows Service host. But please obtain the address via code. In addition, you can refer to http://msdn.microsoft.com/en-us/WAZPlatformTrainingCourse_WindowsAzureRoleCommunicationVS2010Lab for a complete tutorial.
Best Regards,
Ming Xu.
The Add Windows Azure Deployment Project option only appears if the project type is a WebApplication or WCF Application. You have to host your WCF library in a WebApplication and then the option will appear (or even better host it directly in a Windows Azure WebRole project).
If you really want to host your WCF library in a WorkerRole I suggest you do what Ming Xu has explained. But normally you host your WCF services in WebRoles on Windows Azure. So I hope you have a special need that explains why you want to use WorkerRoles.
I hope that helps.

WiX - Restart service after modification of the installed product

I'm writing a MSI which installs a windows service and adds some DLLs which the service uses. Those DLLs are features which can be added or removed using the installer.
After a user modifies the installed product(eq. add a new feature), windows service needs to be restarted. Is there a more elegant way of doing so in WiX 3.5 other than calling a custom action which would restart the service?
This is how I'm starting the service.
<ServiceControl Id="StartService" Name="MyService" Start="install" Stop="both" Remove="uninstall" Wait="yes" />
EDIT:
Here's the complete component code. Disregard the ids.
<Component Id="MyService" Guid="GUID">
<File Id="MyService"
Source="$(var.BuildDestination)/$(var.NameSpacePrefix).MyService.exe"
KeyPath="yes"
>
</File>
<RemoveFile Id='AppConfigFile' On='uninstall' Name='MyService.exe.Config' />
<User xmlns="http://schemas.microsoft.com/wix/UtilExtension"
Id="ServiceAccount"
CreateUser="no"
FailIfExists="no"
RemoveOnUninstall="no"
UpdateIfExists="yes"
Disabled="no"
LogonAsService="yes"
Name="[ACCOUNT]"
Password="[PASSWORD]" />
<ServiceInstall
Id="MyService"
Type="ownProcess"
Vital="yes"
Name="MyService"
DisplayName="MyService"
Description="MyService"
Start="auto"
Account="[ACCOUNT]"
Password="[PASSWORD]"
ErrorControl="ignore"
Interactive="no">
</ServiceInstall>
<ServiceControl Id="StartService"
Name="MyService"
Start="install"
Stop="both"
Remove="both"
Wait="yes"
>
</ServiceControl>
As the state of the service feature(feature which installs and starts the service) wasn't updated, the service itself wasn't stopped and started too.
I've solved the issue by adding ServiceControl to all components which are separate features.
<Component Id="Modules1" Guid="GUID">
<File Id="Modules.1" Source="$(var.BuildDestination)/$(var.NameSpacePrefix)Modules.1.dll" KeyPath="yes">
</File>
<ServiceControl Id="StartService1"
Name="MyService"
Start="install"
Stop="both"
Wait="yes"
>
</ServiceControl>
This solution works for me:
<Component Directory="APPLICATIONFOLDER">
<File Source ="MyService.exe"
KeyPath ="yes" />
<ServiceInstall Id ="MyService.exe"
Name ="My Service"
Account ="LocalSystem"
Start ="auto"
ErrorControl="normal"
Interactive ="no"
Type ="ownProcess"
Description ="My service does stuff."/>
<ServiceControl Id ="MyService.exe"
Name ="My Service"
Start ="install"
Stop ="both"
Remove ="both"
Wait ="no"/>
</Component>