How to allow write permission to AppPoolIdentity user in IIS 10 - windows

I have a website hosted on IIS 10. The website has a feature to write files in a folder. I have given write permission to IIS_IUSER, IUSER and USER groups on the wwwroot folder.However, I still see access denied exception.
One workaround I do is allowing write permission to AppPoolIdentity user (the user with name name as my application name) on the website folder. However, this permission gets removed each time I do a web deploy.
Is there something I am missing? I have windows server 2016.

If you use Web Deploy from Visual Studio, the publish will overwrite the ACLs on the server by clearing them to the inherited defaults of the parent.
To avoid update ACL each time when you publish your web application.
You could add below command in your PublishProfiles's pubxml.
<IncludeSetAclProviderOnDestination>False</IncludeSetAclProviderOnDestination>
Details publish profile as below:
<?xml version="1.0" encoding="utf-8"?>
<!--
This file is used by the publish/package process of your Web project. You can customize the behavior of this process
by editing this MSBuild file. In order to learn more about this please visit https://go.microsoft.com/fwlink/?LinkID=208121.
-->
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<WebPublishMethod>MSDeploy</WebPublishMethod>
<LastUsedBuildConfiguration>Release</LastUsedBuildConfiguration>
<LastUsedPlatform>Any CPU</LastUsedPlatform>
<SiteUrlToLaunchAfterPublish />
<LaunchSiteAfterPublish>True</LaunchSiteAfterPublish>
<ExcludeApp_Data>False</ExcludeApp_Data>
<MSDeployServiceURL>http://localhost:9825/</MSDeployServiceURL>
<DeployIisAppPath>WebFormApplication</DeployIisAppPath>
<RemoteSitePhysicalPath />
<SkipExtraFilesOnServer>True</SkipExtraFilesOnServer>
<MSDeployPublishMethod>InProc</MSDeployPublishMethod>
<EnableMSDeployBackup>False</EnableMSDeployBackup>
<UserName />
<_SavePWD>False</_SavePWD>
<IncludeSetAclProviderOnDestination>False</IncludeSetAclProviderOnDestination>
<PublishDatabaseSettings>
<Objects xmlns="">
<ObjectGroup Name="DefaultConnection" Order="1" Enabled="False">
<Destination Path="" />
<Object Type="DbCodeFirst">
<Source Path="DBContext" DbContext="WebFromIdentityTest.Models.ApplicationDbContext, WebFromIdentityTest" Origin="Configuration" />
</Object>
</ObjectGroup>
</Objects>
</PublishDatabaseSettings>
</PropertyGroup>
<ItemGroup>
<MSDeployParameterValue Include="$(DeployParameterPrefix)DefaultConnection-Web.config Connection String" />
</ItemGroup>
</Project>

Related

Shared Publish Profiles with User Specific variables

We have a complex visual studio publish profile for developers to deploy files. I want developers to all to use the same publish profile whilst have some variables configurable for each individual user that don't get checked in to source control. Is this possible? If so then how?
<?xml version="1.0" encoding="utf-8"?>
<!--
This file is used by the publish/package process of your Web project. You can customize the behavior of this process
by editing this MSBuild file. In order to learn more about this please visit https://go.microsoft.com/fwlink/?LinkID=208121.
-->
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<WebPublishMethod>FileSystem</WebPublishMethod>
<PublishProvider>FileSystem</PublishProvider>
<LastUsedBuildConfiguration>Debug</LastUsedBuildConfiguration>
<LastUsedPlatform>Any CPU</LastUsedPlatform>
<SiteUrlToLaunchAfterPublish />
<LaunchSiteAfterPublish>True</LaunchSiteAfterPublish>
<ExcludeApp_Data>False</ExcludeApp_Data>
<DeleteExistingFiles>False</DeleteExistingFiles>
<PipelineDependsOn>
CopyAssets;
$(PipelineDependsOn);
</PipelineDependsOn>
<publishUrl>C:\inetpub\wwwroot\local.MyApp\Website</publishUrl>
</PropertyGroup>
<Target Name="CopyAssets">
<Message Text="Inside of CopyAssets" Importance="high"/>
<Exec Command="%WINDIR%\System32\WindowsPowerShell\v1.0\powershell.exe -File "$(SolutionDir)Foundation\Scripts\Powershell\CopyAssets.ps1" $(SolutionDir) $(publishUrl)"/>
</Target>
</Project>
This is it in its simplest form. In this example I'd want developers to configure for example publish URL on a per user basis ideally in the .user file if possible or get a variable or parameter from somewhere we can pass into this publish profile.
I resolved this by creating a .wpp.targets file. I created one within the project I am publishing. This allowed me to define the Powershell I am running to run for all publish profiles.
This enabled me to allow developers to define their own publish profiles and still run the script allowing the publish URL value to be individual for each developer.
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<PipelineDependsOn>
CopyAssets;
$(PipelineDependsOn);
</PipelineDependsOn>
</PropertyGroup>
<Target Name="CopyAssets">
<Message Text="Inside of CopyAssets" Importance="high"/>
<Exec Command="%WINDIR%\System32\WindowsPowerShell\v1.0\powershell.exe -File "$(SolutionDir)Foundation\Scripts\Powershell\CopyAssets.ps1" $(SolutionDir) $(publishUrl)"/>
</Target>
</Project>
I removed the PipelineDepndsOn part from my publish profile and did it in the target file as I defined above.

wpp.targets to change folder permissions - only first folder permissions are applied

I am deploying to elastic beanstalk via Visual Studio 2013.
Here is my wpp.targets file:
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Target Name="SetupCustomAcls" AfterTargets="AddIisSettingAndFileContentsToSourceManifest">
<ItemGroup>
<MsDeploySourceManifest Include="setAcl">
<Path>$(_MSDeployDirPath_FullPath)\ChatFiles</Path>
<setAclAccess>Read,Write</setAclAccess>
<setAclResourceType>Directory</setAclResourceType>
<AdditionalProviderSettings>setAclResourceType;setAclAccess</AdditionalProviderSettings>
</MsDeploySourceManifest>
<MsDeploySourceManifest Include="setAcl">
<Path>$(_MSDeployDirPath_FullPath)\FileHoldingForS3</Path>
<setAclAccess>Read,Write</setAclAccess>
<setAclResourceType>Directory</setAclResourceType>
<AdditionalProviderSettings>setAclResourceType;setAclAccess</AdditionalProviderSettings>
</MsDeploySourceManifest>
<MsDeploySourceManifest Include="setAcl">
<Path>$(_MSDeployDirPath_FullPath)\FileHoldEmail</Path>
<setAclAccess>Read,Write</setAclAccess>
<setAclResourceType>Directory</setAclResourceType>
<AdditionalProviderSettings>setAclResourceType;setAclAccess</AdditionalProviderSettings>
</MsDeploySourceManifest>
</ItemGroup>
</Target>
<Target Name="DeclareCustomParameters" AfterTargets="AddIisAndContentDeclareParametersItems">
<ItemGroup>
<MsDeployDeclareParameters Include="FilesSetAclParam">
<Kind>ProviderPath</Kind>
<Scope>setAcl</Scope>
<Match>^$(_EscapeRegEx_MSDeployDirPath)\\ChatFiles$</Match>
<Description>Add write permission to the ChatFiles folder.</Description>
<DefaultValue>{$(_MsDeployParameterNameForContentPath)}/ChatFiles</DefaultValue>
<Value>$(_DestinationContentPath)/ChatFiles</Value>
<Tags>Hidden</Tags>
<Priority>$(VsSetAclPriority)</Priority>
<ExcludeFromSetParameter>True</ExcludeFromSetParameter>
</MsDeployDeclareParameters>
<MsDeployDeclareParameters Include="FilesSetAclParam">
<Kind>ProviderPath</Kind>
<Scope>setAcl</Scope>
<Match>^$(_EscapeRegEx_MSDeployDirPath)\\FileHoldingForS3$</Match>
<Description>Add write permission to the FileHoldingForS3 folder.</Description>
<DefaultValue>{$(_MsDeployParameterNameForContentPath)}/FileHoldingForS3</DefaultValue>
<Value>$(_DestinationContentPath)/FileHoldingForS3</Value>
<Tags>Hidden</Tags>
<Priority>$(VsSetAclPriority)</Priority>
<ExcludeFromSetParameter>True</ExcludeFromSetParameter>
</MsDeployDeclareParameters>
<MsDeployDeclareParameters Include="FilesSetAclParam">
<Kind>ProviderPath</Kind>
<Scope>setAcl</Scope>
<Match>^$(_EscapeRegEx_MSDeployDirPath)\\FileHoldEmail$</Match>
<Description>Add write permission to the FileHoldEmail folder.</Description>
<DefaultValue>{$(_MsDeployParameterNameForContentPath)}/FileHoldEmail</DefaultValue>
<Value>$(_DestinationContentPath)/FileHoldEmail</Value>
<Tags>Hidden</Tags>
<Priority>$(VsSetAclPriority)</Priority>
<ExcludeFromSetParameter>True</ExcludeFromSetParameter>
</MsDeployDeclareParameters>
</ItemGroup>
</Target>
But only the folder permissions for the first folder is applied.
I am ensuring that I the wpp.targets file is not cached prior to deployment.
Make sure you didn't instruct MSDeploy to ignore ACLs via the MSDeploy.exe call
,includeAcls="False"
Or in the build:
http://blogs.iis.net/msdeploy/skipping-setting-an-acl-in-a-visual-studio-2010-deployment-package
The issue was that for each:
MsDeployDeclareParameters Include="FilesSetAclParam"
The FilesSetAclParam should be unique for each one (of course!)

MSBuild: How to run custom target after _CopyFilesToPublishFolder?

I'm using Visual Studio 2013. I'm trying to publish a ClickOnce application from the command-line by passing /target:publish. However, I would like to do a few extra steps after MSBuild is done copying all the files to the publish folder. This is what I have come up so far:
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<MSBuildCommunityTasksPath>$(SolutionDir)\.build</MSBuildCommunityTasksPath>
<MSBuildCommunityTasksLib>$(MSBuildCommunityTasksPath)\MSBuild.Community.Tasks.dll</MSBuildCommunityTasksLib>
<ClickOnceBuildDirectory>$(ProjectDir)\bin\app.publish</ClickOnceBuildDirectory>
</PropertyGroup>
<Import Project="$(MSBuildCommunityTasksPath)\MSBuild.Community.Tasks.targets" />
<UsingTask TaskName="FileUpdate" AssemblyFile="$(MSBuildCommunityTasksLib)" />
<Target Name="CustomPostPublishActions" AfterTargets="PublishBuild" >
<!-- Create directory -->
<MakeDir Directories="$(ProjectDir)..\Deploy\Client\Application Files" />
<!-- Copy published website to deployment location -->
<ItemGroup>
<_CopyItems Include="$(ClickOnceBuildDirectory)\**\*.*" />
</ItemGroup>
<Copy SourceFiles="#(_CopyItems)" DestinationFolder="$(ProjectDir)..\Deploy\Client" />
<!-- Write publish.htm file for ClickOnce -->
<Copy SourceFiles="$(ProjectDir)\..\..\Build\publish.htm" DestinationFiles="$(ProjectDir)..\Deploy\Client\publish.htm" />
<FileUpdate Files="$(ProjectDir)..\Deploy\Client\publish.htm" Regex="{VERSION}" IgnoreCase="true" Multiline="true" Singleline="false" ReplacementText="$(ApplicationVersion)" />
</Target>
</Project>
Unfortunately, this is the order that the targets get run:
CustomPostPublishActions:
Creating directory "C:\MyProject\..\Deploy\Client\Application Files".
Copying file from "C:\MyProject\\bin\app.publish\DeploymentScheduler.exe" to "C:\MyProject\..\Deploy\Client\DeploymentScheduler.exe".
Copying file from "C:\MyProject\\..\..\Build\publish.htm" to "C:\MyProject\..\Deploy\Client\publish.htm".
Updating File "C:\MyProject\..\Deploy\Client\publish.htm".
_CopyFilesToPublishFolder:
Creating directory "bin\app.publish\Application Files\MyApplication_1_0_0_0".
Copying file from "bin\MyProject.exe.manifest" to "bin\app.publish\Application Files\MyProject_1_0_0_0\MyProject.exe.manifest".
Copying file from "bin\app.publish\MyProject.exe" to "bin\app.publish\Application Files\MyProject_1_0_0_0\MyProject.exe.deploy".
Copying file from "app.config" to "bin\app.publish\Application Files\MyProject_1_0_0_0\MyProject.exe.config.deploy".
Copying file from "obj\Debug\MyProject.pdb" to "bin\app.publish\Application Files\MyProject_1_0_0_0\MyProject.pdb.deploy".
1>Done Building Project
Basically, how do I get my target "CustomPostPublishActions" to run AFTER "_CopyFilesToPublishFolder"? Is it even possible? Any help is really appreciated!
There are predefined targets that can be overwritten to run before or after publish, update your script like this:
<Target Name="AfterPublish">
<!-- Create directory -->
<MakeDir Directories="$(ProjectDir)..\Deploy\Client\Application Files" />
<!-- Copy published website to deployment location -->
<ItemGroup>
<_CopyItems Include="$(ClickOnceBuildDirectory)\**\*.*" />
</ItemGroup>
<Copy SourceFiles="#(_CopyItems)" DestinationFolder="$(ProjectDir)..\Deploy\Client" />
<!-- Write publish.htm file for ClickOnce -->
<Copy SourceFiles="$(ProjectDir)\..\..\Build\publish.htm" DestinationFiles="$(ProjectDir)..\Deploy\Client\publish.htm" />
<FileUpdate Files="$(ProjectDir)..\Deploy\Client\publish.htm" Regex="{VERSION}" IgnoreCase="true" Multiline="true" Singleline="false" ReplacementText="$(ApplicationVersion)" />
</Target>
This link will give you an idea of the existing overridable targets and how you can work with them.

WiX 3.8 website installer - nothing happens on executing MSI

I am using WiX 3.8 to build a website installer for a MVC web API project. I have successfully followed the steps of a tutorial and created the MSI file that should just copy all the web app files to my IIS folder. However on executing it, I don't see any files copied and the MSI exits without any error. I checked in the event log as well, where it says that the installer ran successfully. Below is the MS Build file:
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="3.5" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<WebSiteSource>..\API\</WebSiteSource>
<SetupF>..\Setup\</SetupF>
<PublishF>publish\</PublishF>
<Publish>$(SetupF)$(PublishF)</Publish>
<WebSiteContentCode>WebAPIContent.wxs</WebSiteContentCode>
<WebSiteContentObject>WebSiteContent.wixobj</WebSiteContentObject>
<MsiOut>bin\Release\Setup.msi</MsiOut>
</PropertyGroup>
<!-- Defining group of temporary files which is the content of the web site. -->
<ItemGroup>
<WebSiteContent Include="$(WebSiteContentCode)" />
</ItemGroup>
<!-- The list of WIX input files -->
<ItemGroup>
<WixCode Include="Product.wxs" />
<WixCode Include="$(WebSiteContentCode)" />
</ItemGroup>
<Target Name="Build">
<!-- Compile in release mode -->
<MSBuild Projects="..\API\API.csproj" Targets="ReBuild" Properties="Configuration=Release" />
</Target>
<Target Name="PublishWebsite">
<!-- Remove complete publish folder in order to be sure that evrything will be newly compiled -->
<Message Text="Removing publish directory: $(SetupF)"/>
<RemoveDir Directories="$(SetupF)" ContinueOnError="false" />
<Message Text="Start to publish website" Importance="high" />
<MSBuild Projects="..\API\API.csproj" Targets="ResolveReferences;_CopyWebApplication" Properties="OutDir=$(Publish)bin\;WebProjectOutputDir=$(Publish);Configuration=Release" />
</Target>
<Target Name="Harvest">
<!-- Harvest all content of published result -->
<Exec
Command='"$(Wix)bin\heat" dir $(Publish) -dr INSTALLFOLDER -ke -srd -cg apicomponents -var var.publishDir -gg -out $(WebSiteContentCode)'
ContinueOnError="false"
WorkingDirectory="." />
</Target>
<Target Name="WIX">
<Message Text="TEST: #(WixCode)"/>
<Exec
Command='"$(Wix)bin\candle" -dpublishDir=$(Publish) -dMyWebResourceDir=. #(WixCode, &apos; &apos;)'
ContinueOnError="false"
WorkingDirectory="." />
<Exec
Command='"$(Wix)bin\light" WebAPIContent.wixobj Product.wixobj -out $(MsiOut)'
ContinueOnError="false"
WorkingDirectory="." />
<Message Text="Install package has been created." />
</Target>
</Project>
Product.wxs
<?xml version="1.0" encoding="UTF-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
<Product Id="*" Name="ApiSetup" Language="1033" Version="1.0.0.0" Manufacturer="Fingent" UpgradeCode="20e8d558-9fc4-4bd3-9842-76ae40edd994">
<Package InstallerVersion="200" Compressed="yes" InstallScope="perMachine" />
<MajorUpgrade DowngradeErrorMessage="A newer version of API is already installed." />
<Media Id="1" Cabinet="api.cab" EmbedCab="yes" />
<Feature Id="ProductFeature" Title="api.Setup" Level="1">
<ComponentGroupRef Id="apicomponents" />
</Feature>
</Product>
<Fragment>
<!-- Will default to C:\ if that is the main disk -->
<Directory Id="TARGETDIR" Name="SourceDir">
<!-- Will reference to C:\wwwroot-->
<Directory Id="INETPUB" Name="Inetpub">
<!-- Will reference to c:\wwwroot\api-->
<Directory Id="INSTALLFOLDER" Name="api" />
</Directory>
</Directory>
</Fragment>
</Wix>
As you can see I have used Heat to generate the files list. The WXS file for it is correctly generated and I also get the OBJ files and the MSI, but nothing is done after its execution. Please help.
The problem might be due to following reasons:
1) In HeatFile.wxs generation. The HeatFile.wxs might have been generated successfully but it may not contain the directory to which the software needs to be installed.
For this, add -dr yourinstallationdirectory tag to your command line while generating HeatFile.wxs.
Complete command looks like:
heat.exe dir "path to directory which needs to be harvested" -dr INSTALLDIR -cg Components -gg -g1 -srd -var var.MyDir -out HeatFile.wxs
2) However, you found that your TARGETDIR turns out to be D:\ drive. This happens because wix search for the Directory with most free disk space and install your msi in that directory by default.
But you can change your root directory using the following tag:
< SetDirectory Id="TARGETDIR" Value="C:\" / >
Hope this helps :)

MSDeploy skip rules when using MSBuild PublishProfile with Visual Studio 2012

I'm trying to use WebDeploy to publish a website using custom MSDeploy skip rules and a publish profile saved in Visual Studio 2012.
I have the publish profile working from the command line, but the skip rule to skip deleting a folder isn't working.
I have an ErrorLog subfolder in my web app with a web.config file inside it to set the proper folder permissions. Without any skip rules, the ErrorLog folder and web.config file are published normally, but all existing error log files in the folder on the server are deleted on publish.
Error with <SkipAction>Delete</SkipAction>
When I add a custom skip rule to my wpp.targets file, the skip rule is no longer accepting a value for the <SkipAction> element. If I set <SkipAction>Delete</SkipAction>, I get the following error:
C:\Program Files (x86)\MSBuild\Microsoft\VisualStudio\v11.0\Web\Microsoft.Web.Publishing.targets(4377,5): error : Web deployment task failed. (Unrecognized skip directive 'skipaction'. Must be one of the following: "objectName," "keyAttribute," "absolutePath," "xPath," "attributes.<name>.") [C:\inetpub\wwwroot\My.Website\My.Website\My.Website.csproj]
If I simply omit the <SkipAction> element, the ErrorLog folder is deleted when it would normally be published.
If I set <SkipAction></SkipAction>, again, the ErrorLog folder is deleted on publish.
If I set <KeyAttribute>Delete</KeyAttribute>, then ErrorLog and the web.config file are published normally.
My understanding is that in order to use custom skip rules, you need to call MSBuild from the command line instead of publishing from within VS 2012. I'd still like to use my saved publishing profiles, however, and I understand that's now possible as of VS 2012.
My MSBuild command line:
C:\Windows\Microsoft.NET\Framework\v4.0.30319\MSBuild.exe My.Website.sln /p:Configuration=Release;DeployOnBuild=true;PublishProfile="Test Server - Web Deploy"
My.Website.wpp.targets:
<?xml version="1.0" encoding="utf-8" ?>
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<AfterAddIisSettingAndFileContentsToSourceManifest>AddCustomSkipRules</AfterAddIisSettingAndFileContentsToSourceManifest>
</PropertyGroup>
<Target Name="AddCustomSkipRules">
<Message Text="Adding Custom Skip Rules" />
<ItemGroup>
<MsDeploySkipRules Include="SkipErrorLogFolder1">
<SkipAction></SkipAction>
<KeyAttribute>Delete</KeyAttribute>
<ObjectName>dirPath</ObjectName>
<AbsolutePath>$(_Escaped_WPPAllFilesInSingleFolder)\\ErrorLog$</AbsolutePath>
<XPath></XPath>
</MsDeploySkipRules>
</ItemGroup>
</Target>
</Project>
My MSBuild output showing the custom skip rule, but still deleting the files:
GenerateMsdeployManifestFiles:
Generate source manifest file for Web Deploy package/publish ...
AddCustomSkipRules:
Adding Custom Skip Rules
MSDeployPublish:
Start Web Deploy Publish the Application/package to http://testserver.domain.com/MSDEPLOYAGENTSERVICE ...
Starting Web deployment task from source: manifest(C:\inetpub\wwwroot\My.Website\My.Website\obj\Release\Package\My.Website.SourceManifest.xml) to Destination: auto().
Deleting filePath (MyWeb/ErrorLog\test.txt).
Updating setAcl (MyWeb/).
Updating setAcl (MyWeb/).
Updating filePath (MyWeb/ErrorLog\Web.config).
Updating filePath (MyWeb/Web.config).
Updating setAcl (MyWeb/).
Updating setAcl (MyWeb/).
Successfully executed Web deployment task.
Publish is successfully deployed.
Edit: It turns out you are right: the skip directive is ignored when executed from Visual Studio.
Fortunately, there's a workaround.
What you want is this:
<!-- Skip the deletion of any file within the ErrorLog directory -->
<MsDeploySkipRules Include="SkipErrorLogFolder1">
<SkipAction>Delete</SkipAction>
<ObjectName>filePath</ObjectName>
<AbsolutePath>ErrorLog</AbsolutePath>
</MsDeploySkipRules>
In addition, you need to prevent VS from using the UI-task (which appears to contain a bug regarding the skip rules). You can do this by declaring the following in your wpp.targets or pubxml:
<PropertyGroup>
<UseMsDeployExe>true</UseMsDeployExe>
</PropertyGroup>
I've tested this locally and I can confirm that it works as desired: the additional file is updated but no files in the directory are deleted.
For reference, here is my complete .wpp.targets file with working skip rule to skip deleting the ErrorLog folder and custom ACLs to make the ErrorLog folder writable on the server.
As of VS 2012 Update 3, this only works when publishing with MSBuild from the command line with the DeployOnBuild=true;PublishProfile="Test Server - Web Deploy" options passed to MSBuild. This will not work when publishing from within VS.
<?xml version="1.0" encoding="utf-8" ?>
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<UseMsdeployExe>true</UseMsdeployExe> <!-- Required for the MSDeploySkipRules to work -->
<DeployManagedPipelineMode>Integrated</DeployManagedPipelineMode>
</PropertyGroup>
<PropertyGroup>
<AfterAddIisSettingAndFileContentsToSourceManifest>
$(AfterAddIisSettingAndFileContentsToSourceManifest);
AddCustomSkipRules;
</AfterAddIisSettingAndFileContentsToSourceManifest>
</PropertyGroup>
<Target Name="AddCustomSkipRules">
<Message Text="Adding Custom Skip Rules" />
<ItemGroup>
<MsDeploySkipRules Include="SkipErrorLogFolder">
<SkipAction>Delete</SkipAction>
<ObjectName>filePath</ObjectName>
<AbsolutePath>ErrorLog</AbsolutePath>
<XPath></XPath>
</MsDeploySkipRules>
</ItemGroup>
</Target>
<PropertyGroup>
<AfterAddIisSettingAndFileContentsToSourceManifest>
$(AfterAddIisSettingAndFileContentsToSourceManifest);
SetCustomACLs;
</AfterAddIisSettingAndFileContentsToSourceManifest>
<AfterAddDeclareParametersItemsForContentPath>
$(AfterAddDeclareParametersItemsForContentPath);
SetCustomAclParameters;
</AfterAddDeclareParametersItemsForContentPath>
</PropertyGroup>
<Target Name="SetCustomACLs">
<Message Text="Setting Custom ACLs" />
<ItemGroup>
<!--Make sure the application pool identity has write permission to the download folder-->
<MsDeploySourceManifest Include="setAcl"
Condition="$(IncludeSetAclProviderOnDestination) And Exists('$(_MSDeployDirPath_FullPath)\ErrorLog')">
<Path>$(_MSDeployDirPath_FullPath)\ErrorLog</Path>
<setAclAccess>Write</setAclAccess>
<setAclResourceType>Directory</setAclResourceType>
<AdditionalProviderSettings>setAclResourceType;setAclAccess</AdditionalProviderSettings>
</MsDeploySourceManifest>
</ItemGroup>
</Target>
<Target Name="SetCustomAclParameters">
<Message Text="Setting Custom ACL Parameters" />
<EscapeTextForRegularExpressions Text="$(_MSDeployDirPath_FullPath)">
<Output TaskParameter="Result" PropertyName="_EscapeRegEx_MSDeployDirPath" />
</EscapeTextForRegularExpressions>
<ItemGroup>
<MsDeployDeclareParameters Include="Add write permission to ErrorLog folder"
Condition="$(IncludeSetAclProviderOnDestination) and Exists('$(_MSDeployDirPath_FullPath)\ErrorLog')">
<Kind>ProviderPath</Kind>
<Scope>setAcl</Scope>
<Match>^$(_EscapeRegEx_MSDeployDirPath)\\ErrorLog$</Match>
<Description>Add write permission to ErrorLog folder</Description>
<DefaultValue>Default Web Site/ErrorLog</DefaultValue>
<Value>$(DeployIisAppPath)/ErrorLog</Value>
<Tags>Hidden</Tags>
<Priority>$(VsSetAclPriority)</Priority>
<ExcludeFromSetParameter>True</ExcludeFromSetParameter>
</MsDeployDeclareParameters>
</ItemGroup>
</Target>
</Project>
Another approach is to avoid the SkipAction tag, I've successfully used this setup directly from VS 2013:
<Target Name="AddCustomSkipRules"
AfterTargets="AddIisSettingAndFileContentsToSourceManifest">
<Message Text="Adding Custom Skip Rules" />
<ItemGroup>
<MsDeploySkipRules Include="SkipMedia">
<objectName>dirPath</objectName>
<absolutePath>media</absolutePath>
</MsDeploySkipRules>
<MsDeploySkipRules Include="SkipUpload">
<objectName>dirPath</objectName>
<absolutePath>upload</absolutePath>
</MsDeploySkipRules>
</ItemGroup>
</Target>
Only caveat as far as I can tell is that, it will ignore both update, delete and add operations.
After many hours looking through the net. i created this file as {myprojectname}.wpp.targets under the site root folder. it works when publishing with visual studio. the media folder is ignored. i am using VS 2010.
<?xml version="1.0" encoding="utf-8" ?>
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<UseMsdeployExe>true</UseMsdeployExe>
<!-- Required for the MSDeploySkipRules to work -->
<DeployManagedPipelineMode>Integrated</DeployManagedPipelineMode>
</PropertyGroup>
<PropertyGroup>
<AfterAddIisSettingAndFileContentsToSourceManifest>
$(AfterAddIisSettingAndFileContentsToSourceManifest);
AddCustomSkipRules;
</AfterAddIisSettingAndFileContentsToSourceManifest>
</PropertyGroup>
<Target Name="AddCustomSkipRules">
<Message Text="Adding Custom Skip Rules - WPP Targets 2" />
<ItemGroup>
<MsDeploySkipRules Include="SkipErrorLogFolder">
<SkipAction>Delete</SkipAction>
<ObjectName>dirPath</ObjectName>
<AbsolutePath>media</AbsolutePath>
<XPath></XPath>
<Apply>Destination</Apply>
</MsDeploySkipRules>
</ItemGroup>
</Target>
</Project>
I think the problem is in incorrect AbsolutePath. It should be a regular expression to match file or folder. so it should be properly escaped. Below is the sample which worked for me (I wanted to skip removal of app_offline.htm to make delivery part of larger deployment)
<PropertyGroup>
<PackageUsingManifestDependsOn>$(PackageUsingManifestDependsOn);AddCustomSkipRules</PackageUsingManifestDependsOn>
</PropertyGroup>
<Target Name="AddCustomSkipRules">
<ItemGroup>
<MsDeploySkipRules Include="SkipAppOfflineOnDeploy">
<SkipAction></SkipAction>
<ObjectName>filePath</ObjectName>
<AbsolutePath>app_offline\.htm</AbsolutePath>
<Apply>Destination</Apply>
<XPath></XPath>
</MsDeploySkipRules>
</ItemGroup>
</Target>
Works for me: My Full prepprod.pubxml file in my App_Data/PublishProfiles folder in my web solution. Web Deploy no longer deletes files out of the cachefiles folder on webdeploy from VS 2015. The first PropertyGroup was auto-generated by using the web publishing gui in Visual Studio. I added the second PropertyGroup, and the Target section from previous comments.
<?xml version="1.0" encoding="utf-8"?>
<!--
This file is used by the publish/package process of your Web project. You can customize the behavior of this process
by editing this MSBuild file. In order to learn more about this please visit http://go.microsoft.com/fwlink/?LinkID=208121.
-->
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<WebPublishMethod>MSDeploy</WebPublishMethod>
<LastUsedBuildConfiguration>Production</LastUsedBuildConfiguration>
<LastUsedPlatform>Any CPU</LastUsedPlatform>
<SiteUrlToLaunchAfterPublish>{masked}</SiteUrlToLaunchAfterPublish>
<LaunchSiteAfterPublish>True</LaunchSiteAfterPublish>
<ExcludeApp_Data>False</ExcludeApp_Data>
<MSDeployServiceURL>{masked}</MSDeployServiceURL>
<DeployIisAppPath>{masked}</DeployIisAppPath>
<RemoteSitePhysicalPath />
<SkipExtraFilesOnServer>False</SkipExtraFilesOnServer>
<MSDeployPublishMethod>WMSVC</MSDeployPublishMethod>
<MSDeployUseChecksum>true</MSDeployUseChecksum>
<EnableMSDeployBackup>True</EnableMSDeployBackup>
<UserName>{masked}</UserName>
<_SavePWD>True</_SavePWD>
<PublishDatabaseSettings>
<Objects xmlns="">
</Objects>
</PublishDatabaseSettings>
<ExcludeFilesFromDeployment>packages.config;*.bat;*.sln;*.suo,*.p4ignore</ExcludeFilesFromDeployment>
<ExcludeFoldersFromDeployment>packages;cachefiles;.ebextensions</ExcludeFoldersFromDeployment>
</PropertyGroup>
<PropertyGroup>
<AfterAddIisSettingAndFileContentsToSourceManifest>
$(AfterAddIisSettingAndFileContentsToSourceManifest);
AddCustomSkipRules;
</AfterAddIisSettingAndFileContentsToSourceManifest>
</PropertyGroup>
<Target Name="AddCustomSkipRules">
<Message Text="Adding Custom Skip Rules" />
<ItemGroup>
<MsDeploySkipRules Include="SkipcachefilesFolder">
<objectName>dirPath</objectName>
<absolutePath>cachefiles</absolutePath>
</MsDeploySkipRules>
</ItemGroup>
</Target>
</Project>
This worked for me in vs 2015, website project type:
<!--Added inside existing <ProjectGroup> tag-->
<AfterAddIisSettingAndFileContentsToSourceManifest>AddCustomSkipRules</AfterAddIisSettingAndFileContentsToSourceManifest>
<!--Added new ProjectGroup tag inside <Project></Project>-->
<PropertyGroup>
<WebPublishMethod>MSDeploy</WebPublishMethod>
</PropertyGroup>
<!--Added inside existing <Project> tag at the bottom-->
<Target Name="AddCustomSkipRules">
<Message Text="Adding Custom Skip Rules" />
<ItemGroup>
<MsDeploySkipRules Include="SkipConfigFolder">
<SkipAction></SkipAction>
<!--<KeyAttribute>Delete</KeyAttribute>-->
<ObjectName>dirPath</ObjectName>
<AbsolutePath>App_Data\\Composite\\Logfiles</AbsolutePath>
<XPath>
</XPath>
</MsDeploySkipRules>
</ItemGroup>
</Target>

Resources