We have a project web installer that installs, upgrades etc. properly. The only issue is that on upgrade we have a problem with a virtual directory created inside the application manually via the IIS manager. We have some statically linked files which can be installed in different ways, if using a cluster it makes more sense to throw them on a network file share/DFS rather than copy them individually (they are very large).
Is there a way that I can have the Wix Web project installer not remove manually created virtual directories inside our application on an upgrade? Or at least detect them and preserve them?
We are using a standard wix iis installation:
<!-- IIS website. Inside a Component, <WebSite> creates a new Web Site. Outside a Component, it's a look up. -->
<iis:WebSite Id='WS.WebSite'
Description='[WEBSITE]'
Directory='DI.InstallDirectory'>
</iis:WebSite>
<Component Id="CO.VirtualDirectory"
Guid="xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
KeyPath="yes">
<!-- The WebSite attribute ties to a <WebSite> element in the setup file -->
<iis:WebVirtualDir Id="VD.VirtualDirectory"
Alias="[VIRTUALDIRECTORY]"
Directory="DI.InstallDirectory"
WebSite="WS.WebSite" >
<iis:WebDirProperties Id="WP.WebDirProperties" DefaultDocuments="overview.aspx" />
<!-- Turn the Virtual Directory into a web application. -->
<iis:WebApplication Id="WA.WebApplication"
Name="xxx"
WebAppPool="AP.ApplicationPool" />
</iis:WebVirtualDir>
<!-- This is pretty important. If the CreateFolder isn't there the WebVirtualDir won't get created as there are no files in this component.
http://www.mail-archive.com/wix-users#lists.sourceforge.net/msg03483.html -->
<CreateFolder />
</Component>
Related
Our company is developing our new applications using Service Fabric.
A common problem we have, multiple developers use queues, databases, storages that are on remote servers, and each one has different configuration for this, all the settings are stored on ApplicationParameters file per environment, for Local development there is a single Local.5Node.xml. It is very common developers checkin their credentials and overwrite others when we get latest version of these files.
I'm trying to customize the ServiceFabric deployment script 'Deploy-FabricApplication.ps1' to use a custom PublishProfile depending on windows credentials of logged user. I can achieve that updating the deployment file, it works well when we deploy using the publish, but it seems that the default behavior of ServiceFabric when we hit F5(debug) is overwrite the parameters with a specific Local.5Node.xml application parameters.
I explored all service fabric .ps1 files and couldn't find where this is defined. I guess this is defined on .targets file, so I don't know how can I avoid this default behaviour.
Is there any other approach to use custom PublishProfiles on local development machines other than Local.5Node.xml?
I actually just ran into this with setting up some team specific environments. I borrowed information from the following sources:
Web Config Transformation
Replace String In File With MSBUILD
I added multiple parameters files based on what was needed for the different teams. Each one containing their specific resource settings.
I also added a Local.1Node.Template.xml and Local.5Node.Template.xml. I even removed the Local.1Node.xml and Local.5Node.xml from source control and set them up to be ignored while leaving them in the projects so that Visual Studio doesn't think they are truly missing. The contents of the 1Node (5Node is the same except for replacing 1Node with 5Node) are as follows:
<?xml version="1.0" encoding="utf-8"?>
<PublishProfile xmlns="http://schemas.microsoft.com/2015/05/fabrictools">
<ClusterConnectionParameters />
<ApplicationParameterFile Path="..\ApplicationParameters\Local.1Node.$(Configuration).xml" />
</PublishProfile>
I then edited the sfproj file for the Service Fabric project to contain the following MSBuild Task and Target:
<UsingTask TaskName="ReplaceFileText" TaskFactory="CodeTaskFactory" AssemblyFile="$(MSBuildToolsPath)\Microsoft.Build.Tasks.v4.0.dll">
<ParameterGroup>
<InputFilename ParameterType="System.String" Required="true" />
<OutputFilename ParameterType="System.String" Required="true" />
<MatchExpression ParameterType="System.String" Required="true" />
<ReplacementText ParameterType="System.String" Required="true" />
</ParameterGroup>
<Task>
<Reference Include="System.Core" />
<Using Namespace="System" />
<Using Namespace="System.IO" />
<Using Namespace="System.Text.RegularExpressions" />
<Code Type="Fragment" Language="cs">
<![CDATA[
File.WriteAllText(
OutputFilename,
Regex.Replace(File.ReadAllText(InputFilename), MatchExpression, ReplacementText)
);
]]>
</Code>
</Task>
</UsingTask>
<Target Name="UpdateProfile" BeforeTargets="UpdateServiceFabricApplicationManifest">
<ReplaceFileText InputFilename="PublishProfiles\Local.1Node.Template.xml" OutputFilename="PublishProfiles\Local.1Node.xml" MatchExpression="\$\(Configuration\)" ReplacementText="$(Configuration)" />
<ReplaceFileText InputFilename="PublishProfiles\Local.5Node.Template.xml" OutputFilename="PublishProfiles\Local.5Node.xml" MatchExpression="\$\(Configuration\)" ReplacementText="$(Configuration)" />
</Target>
The final step was to setup the different Build Configurations for the teams. I created a FT1-Debug through FT6-Debug based on the Debug configuration in the Service Fabric Service project and the Service Fabric Host project. I left all of my other projects alone.
At this point everyone on the different teams can debug locally with the correct configuration for the cluster they are doing work in just by changing the Build Configuration and pressing F5 to debug.
The VS extension for Service Fabric define a hard coded publish profile when we debug the solution using Visual Studio, it check how many nodes my cluster has and create a link to Local.5Node.xml and Local.1Node.xml depending how many nodes my cluster have.
To accomplish the same results, we end up using custom Application Parameters per developer and each developer update the Publish Profile (Local.5node.xml) to point to their respective Application parameter files.
It is not automated as the required feature, but can solve the main problem.
I am really struggling to create a Virtual Directory in an existing website in IIS7 using WiX.
To illustrate, what I therefore have are:
1) The IIS Default Website, and
2) Another website which is a container for a number of business applications and we can call "ContainerWebsite".
What I therefore desperately wish to do is create the following using WiX:
a) Create a virtual directory for one of the business applications (let's call it "BusinessApp1") under "ContainerWebsite". The final structure in IIS will therefore look like this "ContainerWebiste\BusinessApp1"
Should the above virtual directory be successful, I intend to create similar virtual directories for the remaining business applications.
b) Create a dedicated IIS Application Pool for each of the business applications installed to the "ContainerWebsite".
I would be extremely grateful for any assistance towards achieving thie.
Thank you.
See http://blog.torresdal.net/2008/10/24/#WebSiteStandardAction, where it goes into creating a custom action to list the existing websites and selecting one from a drop down. I suppose you can just skip the dropdown and specify the specific website to use, then reference it within your iis:WebVirtualDir section, like so:
<iis:WebSite Id="SelectedWebSite" Description="[WEBSITE_DESCRIPTION]">
<iis:WebAddress Id="AllUnassigned" Port="[WEBSITE_PORT]" IP="[WEBSITE_IP]" Header="[WEBSITE_HEADER]" />
</iis:WebSite>
<iis:WebVirtualDir Id="VirtualDir" Alias="[TARGETVDIR]" Directory="INSTALLLOCATION" WebSite="SelectedWebSite">
<iis:WebApplication Id="SimpleWebAppApp" Name="[TARGETVDIR]" WebAppPool="SWAAppPool" />
<iis:WebDirProperties Id="WebVirtualDirProperties" Execute="yes" Script="yes" Read="yes" WindowsAuthentication="no" AnonymousAccess="yes" IIsControlledPassword="yes" />
</iis:WebVirtualDir>
I'm using WiX 3 to setup my Web Application and most of the cases I'm just installing new versions of the project on the top of the current version, like upgrading the web app every week or so.
I wonder if is there a way to explicit ask IIS to Recycle a given Application Pool via WiX (remove-and-create-again it's not suitable in my case), if not, do we have a way to work around to accomplish that?
Create a custom action that calls appcmd.exe with the recycle command.
In your case:
<Product>
. . .
<CustomAction Id="CA_RecycleAppPool"
Execute="deferred"
Impersonate="no"
Return="check"
Directory="TARGETDIR"
ExeCommand="[SystemFolder]inetsrv\appcmd recycle apppool /apppool.name:"[APPPOOLNAME]"" />
<InstallExecuteSequence>
<Custom Action="CA_RecycleAppPool" Before="InstallFinalize" />
</InstallExecuteSequence>
</Product>
I try to create installer, where web site is creates too.
I use the following code
....
<DirectoryRef Id="WEBFOLDER">
<Component Id="WebLibraries" Guid="77532F98-BF0B-4b9d-98AF-15618691A090" KeyPath="yes">
<iis:WebSite Id="DefaultWebSite" Description="Default Web Site" Directory="WEBFOLDER">
<iis:WebAddress Id="AllUnassigned" Port="80" />
</iis:WebSite>
</Component>
</DirectoryRef>
....
<Feature Id="WebSite" Level="1" Title="Web site">
<ComponentRef Id="WebLibraries" />
</Feature>
....
but when i try to install a created package on machine where iis is not installed, i have got this message even i don't check this feature:
cannot connect to internet information server
Can anybody help me with this trouble?
Thanks in advance.
You're installing your package on a machine where IIS is not installed. What would you expect? :)
To be serious, the WiX IIsExtension (the one which defines WebSite element) uses the API of IIS component to actually do its job. For WiX v3.0 it even requires IIS 6 compatibility to be turned ON in IIS 7 in order to work correctly.
Your component, which contains WebSite element, is not conditioned. this means it will always be installed. When it is installed, the IIsExtension tries to create a website defined in it (if we tell this story short).
So, I would recommend you to do the following (if you wish just skip the IIS part of your installer on target machines like that):
add a launch condition to check if the IIS component is installed (you can rely on IISMAJORVERSION property defined by IIsExtension itself)
condition your component (or feature) which is dependent on IIS with "NOT IISMAJORVERSION" condition
As a result, when IISMAJORVERSION property is not set (IIS is not installed), your component will not be scheduled for install and the IIS custom actions won't run.
P.S. The SKIPCONFIGUREIIS property I initially meant is "all-or-nothing" switch, and is not an appropriate tool for your case.
The Wix WebSite action has to be specified outside of a Component if you want to safely use the Default Web Site (by safely I mean the installer won't remove the default site on uninstall).
<Fragment>
<iis:WebSite Id="DefaultWebSite" Description="Default Web Site" Directory="INSTALLDIR">
<iis:WebAddress Id="AllUnassigned" Port="80" />
</iis:WebSite>
</Fragment>
My installer has a bunch of Features, and some are only enabled when IIS is installed. Disabling the features based on Conditions works fine, and no virtual directories or sites are created, but during install MSI still tries to contact IIS due to the WebSite action and fails on a machine without IIS installed:
"Cannot connect to Internet Information Server. (-2137221164 )"
I found something about SKIPCONFIGUREIIS but this doesn't seem to work in Wix 3.
This saved me from a lot of grief! Just wanted to add that the above will skip IIS configuration on uninstall regardless of installation state. I.E. if the feature was installed the virtual directory will not be removed from IIS on uninstall.
This seems to work for me:
<InstallExecuteSequence>
<!-- Disable ConfigureIIS if we don't need it: -->
<Custom Action="ConfigureIIs" After="InstallFiles"><![CDATA[&Web=3 OR !Web=3]]></Custom>
</InstallExecuteSequence>
I managed to solve this in Wix 3 using the Custom Action Conditions support in InstallExecuteSequence. This example assumes the feature "Web" is the only one that requires we perform IIS actions:
<InstallExecuteSequence>
<!-- Disable ConfigureIIS if we don't need it: -->
<Custom Action="ConfigureIIs" After="InstallFiles">(&Web = 3)</Custom>
</InstallExecuteSequence>
I just looked and found, in a WIX-generated MSI, the condition NOT SKIPCONFIGUREIIS AND VersionNT > 400 associated to the ConfigureIis row in the InstallExecuteSequence table.
In other words you could also use a Custom action like this:
<InstallExecuteSequence>
<!-- Disable the ConfigureIIs action if we don't need it: -->
<Custom Action="CA.SkipConfigureIIs"
After="InstallFiles">NOT &F.IisFeature = 3</Custom>
</InstallExecuteSequence>
<CustomAction Id="CA.SkipConfigureIIs"
Property="SKIPCONFIGUREIIS"
Value="1"
Return="check" />