Wix Installer - Preserve Application Pool User on Upgrade - c#

I have a WIX installer which creates an app pool as follows, using ApplicationPoolIdentity as a default identity.
<Component Id="MyConsoleAppPool" Guid="{my_guid_here}" KeyPath="yes" NeverOverwrite="yes" Win64="yes">
<iis:WebAppPool Id="MyAppPool"
Name="My Web Console"
ManagedPipelineMode="Integrated"
ManagedRuntimeVersion="v4.0" />
</Component>
Some of our customers choose to change the application pool user to a different (custom) IIS user after installation.
On upgrades, their app pool user is being reset to the default of ApplicationPoolIdentity. This is causing them headaches to deal with on every upgrade.
Is there a way of preserving the existing app pool user, ideally without requiring the user password to be re-entered? We would like this to occur silently during the upgrades.
Note: We have a helper library in C# which can be called via CustomAction if any supporting code is needed there.

The reason the app pool was being reset is that, since it was a component created internally from the installer, it would be fully removed and re-installed on upgrades.
Rather than build the app pool in the "iis:WebAppPool" element, I decided simply to reference the app pool as follows, outside of any WIX component:
<Fragment>
<iis:WebAppPool Id="MyAppPool" Name="My Web Console"/>
</Fragment>
Then I created the following custom actions to handle the app pool create/remove:
<CustomAction Id="CreateIISAppPool"
Directory="TARGETDIR"
ExeCommand="[SystemFolder]inetsrv\appcmd add apppool /name:"My Web Console" /managedRuntimeVersion:"v4.0" /managedPipelineMode:"Integrated"
Execute="deferred"
Return="ignore"
Impersonate="no" />
<CustomAction Id="DeleteIISAppPool"
Directory="TARGETDIR"
ExeCommand="[SystemFolder]inetsrv\appcmd delete apppool "My Web Console""
Execute="deferred"
Return="ignore"
Impersonate="no" />
And the sequencing, which states that the app pool is not touched on any upgrade scenarios:
<InstallExecuteSequence>
<Custom Action="DeleteIISAppPool" Before="CreateIISAppPool">(NOT UPGRADINGPRODUCTCODE) AND (REMOVE="ALL")</Custom>
<Custom Action="CreateIISAppPool" Before="InstallFiles">(NOT UPGRADINGPRODUCTCODE) AND (NOT Installed) AND (NOT REMOVE="ALL")</Custom>
<!-- continue with rest of custom actions here -->
</InstallExecuteSequence>
Note: This solution does not account for a user deleting their app pool manually (by mistake or otherwise). They will need to uninstall their current version and re-install to recreate the app pool. This can be resolved by adding another custom action to look for the app pool, and if it doesn't find it, install it on an upgrade with the UPGRADINGPRODUCTCODE condition.

Related

How to generate msi from windows application

I have a Windows Application class where I have defined my Windows Service, and I need to generate a .msi (installer) from it.
What I have done so far for this is: create a new project in Visual Studio Enterprise 2017 - the project is of type Setup Project for Wix v3 (from Wix Toolset); inside this project I have by default References and Product.wxs. From Add References, Projects, I added the Service project.
One of the sources that I found says all that's needed is to add
Source="$(var.MyApplication.TargetPath)" />
as seen here:
http://wixtoolset.org/documentation/manual/v3/votive/authoring_first_votive_project.html
...but this doesn't work for me because:
undefined preprocessor variable $(var.MyApplication.TargetPath)
I don't know where to define this variable and what is the meaning of this path.
Excerpt here:
<Fragment>
<ComponentGroup Id="ProductComponents" Directory="INSTALLFOLDER">
<!-- TODO: Remove the comments around this Component element and the ComponentRef below in order to add resources to this installer. -->
<Component Id="ProductComponent">
<!-- TODO: Insert files, registry keys, and other resources here. -->
<File Source = "$(var.MyApplication.TargetPath)"/>
</Component>
</ComponentGroup>
Any ideas?
Thanks.
This is all autoenerated code except for the File Source line. Don't know what I should add for INSTALLFOLDER either and what the syntax should be.
The purpose is to generate the .msi from my windows service
The Wix documentation for this step is broken as of at least version 3.11.
Instead of creating two separate solutions (app and Wix) you need to add the Wix setup as a second project in your windows forms solution. In the app Solution Explorer pane right-click on the solution then choose Add > New Project. Choose a name like WixSetup.
Next, click on the WixSetup project > References and choose Add New Reference. The projects list should show your app since they are in the same solution.
Next, add the entry to the in Product.wxs but the documentation is incorrect there too, you need to wrap it in a component tab. (Replace MY-APPLICATION-NAME with the name of your windows forms app project.)
<Component Id="ProductComponent">
<File Source="$(var.MY-APPLICATION-NAME.TargetPath)" />
</Component>
You also need to edit line 3 of the .wsx to include a non-empty company name or to remove that attribute:
<Product Id="*" Name="WixSetup" Language="1033" Version="1.0.0.0" Manufacturer="MY-COMPANY"
Finally, you must have a release build in your main application before building the Wix MSI.

User Account Control on OK Button

I have researched over the internet about the UAC functionality on the form OK button but couldn't get the information. All of the information related to implementing the UAC is they relaunch the application with the administrative privileges.
My requirement is to make the application in which when user click on OK button with Shield Icon on it, user will be able to save some information in the windows Registry through elevate the user privilege but I don't want to relaunch the application with administrator rights.
Relaunching the application (or launching a helper application) is what you do. It is the requesting of elevated privileges while launching an application that causes the UAC confirmation screen to appear. The purpose of showing the shield icon is to let the user know that confirmation screen is coming up, basically.
You don't have to just relaunch your application. If your application allows multiple instances, you can launch a second copy with command-line parameters indicating the registry change to make. Or you can have a helper application that does admin things, and launch that as needed. A helper application doesn't need to create or show a window; it can be an entirely background operation.
May be you should add an application manifest and require administrator rights:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
<security>
<requestedPrivileges>
<requestedExecutionLevel level="requireAdministrator" uiAccess="false"/>
</requestedPrivileges>
</security>
</trustInfo>
</assembly>
Edit
It may not be the best solution here, because the entire application is running under elevated privileges and that can be a security vulnerability.

How can I know if my windows service is already installed, using wix

I use WIX for installing an application & a service,
If I install the service for the first time, I want it to be "disabled" and that works fine by setting the field Start="disabled" in the serviceInstall element.
If I install (upgrade) the service while it is already installed on the computer and is set to "Automatic", I want the service to be "Automatic" after the upgrade too, and I can't get this behaviour, The service is upgraded and set as "disabled".
I tried to do this by using 2 serviceInstall element, in one of them Start="disabled" and in the other Start="Auto".
I added a condition to each of my serviceInstall that asks if the service is installed already.
I guess my conditions are not good....
What is the best way for this?
Thanks a lot
I recently encountered a similar problem as well, and the way I approached it is using custom actions after the install. It'll look something like this:
<CustomAction Id="SetStartUpType" BinaryKey="CA.SetStartUpType" DllEntry="CustomAction" Execute="immediate" Return ="check"/>
<Binary Id="CA.SetStartUpType" SourceFile="../WixCustomAction/bin/$(var.BUILD)/WixCustomAction.CA.dll" />
<InstallExecuteSequence>
<Custom Action='SetStartUpType' After='InstallFinalize'>Installed</Custom>
</InstallExecuteSequence>
Setting the custom action condition to "Installed" makes sure that it only changes the startup type if it is already installed. So in your wix file you probably just need one serviceinstall element with start="disabled" for the first install to be disabled.
And thanks to Peter Kelly, there is a way to manually change the service startup types and start the services (if you wish) in your custom actions file. Details can be found here

Application manifest, admin rights and autostart on Windows Vista\7

So, I have an app that needs admin rights to work.
I created an app.manifest file. It works perfectly.
But now I need to set my program to autostart in Windows, and I am having trouble with this. If my program has an app.manifest file - program does not load when windows starts, but when I delete the app.manifest file - it works well.
Here is code from the app.manifest file:
<?xml version="1.0" encoding="utf-8"?>
<asmv1:assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1" xmlns:asmv1="urn:schemas-microsoft-com:asm.v1" xmlns:asmv2="urn:schemas-microsoft-com:asm.v2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<assemblyIdentity version="1.0.0.0" name="update.app"/>
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v2">
<security>
<requestedPrivileges xmlns="urn:schemas-microsoft-com:asm.v3">
<requestedExecutionLevel level="requireAdministrator" uiAccess="false" />
</requestedPrivileges>
</security>
</trustInfo>
<compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
<application>
<supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}"/>-->
</application>
</compatibility>
</asmv1:assembly>
Thanks for your help.
It’s not running because when you request admin access, the user needs to authorize it as admin (click the UAC Allow button), if it’s not popping up, there should be something in the icon-tray where the user can load all blocked exe's by clicking through the icon to give admin rights. when you run without the manifest, it is running only because it defaults to running under standard access (non-admin access, basic user level rights) so you're app is running but without being able to make changes to the system or file/path access items that only admin elevated apps can do. Get me?
The question is, how do you get your exe to auto start with admin privileges if it was installed and initially ran with admin elevated privileges during its installation? There seems to be a few answers to this but i am still searching for which one(s) actually work and are reliable. Basically, if it was elevated once, it should continue to be elevated (automatically, without prompting user) when it’s auto-starting (right after reboots) - but it is NOT doing that, and that's the problem. Let me know if you make progress with this.
UPDATE: 2012.11.10:
I have found a solution, using windows task scheduler to
programmatically schedule as task (that being, to run an EXE during
reboot/startup) & you have the option to run it as an elevated app,
and I think you need to be elevated to begin with in order to be able
to schedule this elevated auto run entry in the windows task
scheduler. Seems weird I know, but MS has allowed for this (and only
this) as a way to auto elevate your apps during startup, and they
haven't provided another way to do this. So, use appropriate API's to
register a Windows Task Schedule which will run your app elevated.
I'm not sure but it's probably about the authentication of startup user. if you did not already, you may check there for detailed information.

How does one stop a Windows service to do an upgrade install?

I have developed a Windows service along with a setup project using Visual Studio 2008. When I do an upgrade install I get the following warning:
The following applications are using files which the installer must update. You can either close the applications and click "Try Again", or click "Continue" so that the installer continues the installation, and replaces these files when your system restarts.
I would like to stop the Windows service during the upgrade install. I have tried creating a custom action and overriding the OnBeforeInstall methoc, however this gets called too late after the warning pop-up message has already occurred.
Is there any way to accomplish this as part of the msi installer. I would prefer to not have to do this as a separate task prior to executing the msi installer.
Update:
Based on further research I have found that the MSI database does support this, however the built-in Visual Studio installer (setup) projects do not provide a means to do this. One must either tweak the MSI database, or go with WiX or a commercial installer.
If you want to go down the route of editing the MSI ServiceControl table, this following VBS script worked for me:
Dim installer, database, view, result
Set installer = CreateObject("WindowsInstaller.Installer")
Set database = installer.OpenDatabase ("Installer.msi", 1)
Set view = database.OpenView("INSERT INTO ServiceControl (ServiceControl,Name,Event,Arguments,Wait,Component_) VALUES ('ServiceName','ServiceName',170,null,null,'C__751A71A3822A287367770DB29839A759')")
view.Execute
database.Commit
Set database = nothing
Look at: Upgrade a Windows Service without Uninstalling
Its already been built in to the MSI / Windows Installer ... the only problem is that the .NET installer classes doesn't use the MSI "Service Installation" features. What is actually happening is that the MSI is trying to install files and run a custom command using the files just copied (that is all Visual Studio is putting in the MSI).
To solve it you can edit the MSI with ORCA and add the following row to the ServiceControl table:
1 ServiceName 170 1 C__489628C5CC1144CB47F43E8BE7F3F31D
The Component ID you can lookup from the FILES table ... I just chose the main EXE file's Component ID. The 170 is a bitmap that tells the Windows Installer to stop and delete the service when Installing and Uninstalling.
This will clear the road for the .NET installers to add service and you can use the ServiceController to start the service after it's been installed via custom command.
In WIX, I was able to get the service to shutdown before upgrade and uninstall by adding a "ServiceControl" element to stop the service on install. This seems to do the job, but everything related to MSI is close to black magic, so I am certainly open to any comments. Below is what my service component is defined as:
<Component Id="ServicePrima" Guid="{d0847344-8632-4326-986c-78f4e02a41bb}">
<ServiceControl Id="ServicePrima_BeforeInstall" Name="ServicePrima" Stop="install" Wait="yes"/>
<File Name="PrimaPro.ServicePrima.Check.cmd" />
<File Name="PrimaPro.ServicePrima.exe" Id="ServicePrimaExe" KeyPath="yes" />
<File Name="PrimaPro.ServicePrima.exe.config" />
<File Name="PrimaPro.ServicePrima.Install.cmd" />
<File Name="PrimaPro.ServicePrima.pdb" />
<File Name="PrimaPro.ServicePrima.Restart.cmd" />
<File Name="PrimaPro.ServicePrima.SignalRestart.cmd" />
<File Name="PrimaPro.ServicePrima.Uninstall.cmd" />
<File Name="PrimaPro.ServicePrima.xml" />
<ServiceInstall Id="ServicePrima_Install" Name="ServicePrima" DisplayName="PrimaPro - ServicePrima"
Type="ownProcess" Start="auto" Interactive="no" ErrorControl="normal"
Description="Manages the database synchronization and configuration management of the PrimaPro System and databases on a machine.">
</ServiceInstall>
<!-- Do not need to start service here (i.e. attribute Start="install"), the service will be started by "RestartServices" custom action. -->
<ServiceControl Id="ServicePrima_AfterInstall" Name="ServicePrima" Stop="uninstall" Remove="uninstall" Wait="yes"/>
</Component>

Categories