我有一个在TeamCity中运行的主要工作的web构建和部署配置,它基本上使用MSBuild将网站自动部署到web服务器。默认情况下,MSDeploy会将目标服务器上的所有内容设置为只读,并且我需要AppPool标识才能对一个文件夹具有写访问权限。
我发现了凯文·利瑟姆的一篇文章,这篇文章让我百分之九十地了解了这一点。Kevin描述了如何通过创建一个名为ProjectName.wpp.targets的文件来挂接MSBuild Web发布管道,如下所示:
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<!--Extends the AfterAddIisSettingAndFileContentsToSourceManifest action do also set ACLs -->
<IncludeCustomACLs>TRUE</IncludeCustomACLs>
<AfterAddIisSettingAndFileContentsToSourceManifest Condition="'$(AfterAddIisSettingAndFileContentsToSourceManifest)'==''">
$(AfterAddIisSettingAndFileContentsToSourceManifest);
SetCustomACLs;
</AfterAddIisSettingAndFileContentsToSourceManifest>
</PropertyGroup>
<Target Name="SetCustomACLs" Condition="'$(IncludeCustomACLs)'=='TRUE'">
<Message Text="Adding Custom ACls" />
<ItemGroup>
<!-- Ensure the AppPool identity has write access to the Files directory -->
<MsDeploySourceManifest Include="setAcl" Condition="$(IncludeSetAclProviderOnDestination)">
<Path>$(_MSDeployDirPath_FullPath)files</Path>
<setAclAccess>Read,Write,Modify</setAclAccess>
<setAclResourceType>Directory</setAclResourceType>
<AdditionalProviderSettings>setAclResourceType;setAclAccess</AdditionalProviderSettings>
</MsDeploySourceManifest>
</ItemGroup>
</Target>
</Project>
这是如此接近工作,它让我发疯。ACL被添加到清单中,但问题是它会根据生成位置生成一个绝对路径,而不是相对于目标服务器上的IIS web应用程序。生成的清单如下所示(为了保护无辜者,一些名称已经更改):
<?xml version="1.0" encoding="utf-8"?>
<sitemanifest>
<IisApp path="C:SolutionPathIisWebAppNamesrcMyProjectNameobjRelease_DeployPackagePackageTmp" managedRuntimeVersion="v4.0" />
<setAcl path="C:SolutionPathIisWebAppNamesrcMyProjectNameobjRelease_DeployPackagePackageTmp" setAclResourceType="Directory" />
<setAcl path="C:SolutionPathIisWebAppNamesrcMyProjectNameobjRelease_DeployPackagePackageTmp" setAclUser="anonymousAuthenticationUser" setAclResourceType="Directory" />
<setAcl path="C:SolutionPathIisWebAppNamesrcMyProjectNameobjRelease_DeployPackagePackageTmpfiles" setAclResourceType="Directory" setAclAccess="Read,Write,Modify" />
</sitemanifest>
这实际上看起来是正确的,最后一行是来自wpp.targets文件的自定义ACL。然而,当MSDeploy将其发送到目标服务器时,会发生以下情况:
2>启动Web Deploy将应用程序/包发布到https://webhostingprovider.biz:8172/msdeploy.axd?site=IisWebAppName。。。2> 正在添加站点清单(站点清单)。2> 正在为路径添加ACL(IisWebAppName)2> 正在为路径添加ACL(IisWebAppName)2> 正在为路径(C:\SolutionPath\IisWebAppname\src\MyProjectName\obj\Release_Deploy\Package\PackageTmp\files)添加ACL2> C:\Program Files(x86)\MSBuild\Microsoft\VisualStudio\v11.0\Web\Microsoft.Web.Publishing.target(4377,5):错误Error_USER_NOT_AUTHORIZED_FOR_SETACL:Web部署任务失败。(使用Web管理服务进行连接时,无法使用指定的提供程序("setAcl")完成操作。如果服务器管理员未授权用户执行此操作,则可能会发生这种情况。setAclhttp://go.microsoft.com/fwlink/?LinkId=178034
整个过程都落在我的自定义ACL路径上,该路径使用绝对路径名,而不是相对于IisWebAppName。我不明白为什么!!
请帮忙:)
您需要创建一个ProviderPath
参数,其中DefaultValue
使用{param name}
语法获取另一个参数的值。
这是我在另一个问题上提供的一个助手,它可以执行所有操作:
<ItemDefinitionGroup>
<AdditionalAcls>
<AclAccess>Write</AclAccess>
<ResourceType>Directory</ResourceType>
</AdditionalAcls>
</ItemDefinitionGroup>
<PropertyGroup>
<AfterAddIisSettingAndFileContentsToSourceManifest>
$(AfterAddIisSettingAndFileContentsToSourceManifest);
AddAdditionalAclsToSourceManifest;
</AfterAddIisSettingAndFileContentsToSourceManifest>
<AfterAddIisAndContentDeclareParametersItems>
$(AfterAddIisAndContentDeclareParametersItems);
AddAdditionalAclsDeclareParameterItems
</AfterAddIisAndContentDeclareParametersItems>
</PropertyGroup>
<Target Name="AddAdditionalAclsToSourceManifest">
<ItemGroup Condition="'@(AdditionalAcls)' != ''">
<MsDeploySourceManifest Include="setAcl">
<Path>$(_MSDeployDirPath_FullPath)%(AdditionalAcls.Identity)</Path>
<setAclResourceType Condition="'%(AdditionalAcls.ResourceType)' != ''">%(AdditionalAcls.ResourceType)</setAclResourceType>
<setAclAccess>%(AdditionalAcls.AclAccess)</setAclAccess>
<AdditionalProviderSettings>setAclResourceType;setAclAccess</AdditionalProviderSettings>
</MsDeploySourceManifest>
</ItemGroup>
</Target>
<Target Name="AddAdditionalAclsDeclareParameterItems">
<ItemGroup Condition="'@(AdditionalAcls)' != ''">
<MsDeployDeclareParameters Include="Add %(AdditionalAcls.AclAccess) permission to %(AdditionalAcls.Identity) Folder">
<Kind>ProviderPath</Kind>
<Scope>setAcl</Scope>
<Match>^$(_EscapeRegEx_MSDeployDirPath)\@(AdditionalAcls)$</Match>
<Description>Add %(AdditionalAcls.AclAccess) permission to %(AdditionalAcls.Identity) Folder</Description>
<DefaultValue>{$(_MsDeployParameterNameForContentPath)}/@(AdditionalAcls)</DefaultValue>
<DestinationContentPath>$(_DestinationContentPath)/@(AdditionalAcls)</DestinationContentPath>
<Tags>Hidden</Tags>
<ExcludeFromSetParameter>True</ExcludeFromSetParameter>
<Priority>$(VsSetAclPriority)</Priority>
</MsDeployDeclareParameters>
</ItemGroup>
</Target>
您可以通过声明来使用它:
<ItemGroup>
<AdditionalAcls Include="MyRelativeWritableDirectory" />
</ItemGroup>
请注意只有当您不需要在路径中使用反斜杠时(即,如果它只是根目录),此解决方案当前才有效。如果你需要一个子目录,你需要窃取我在"SkipDeleteItems"(稍后的答案)中使用的技巧,将regex转义路径元数据添加到每个项目中。