4

我在 TeamCity 中运行了一个大部分工作的 Web 构建和部署配置,它基本上使用 MSBuild 将站点自动部署到 Web 服务器。默认情况下,MSDeploy 将目标服务器上的所有内容都设置为只读,我需要 AppPool 身份才能对一个文件夹具有写入权限。

我发现Kevin leetham 的一篇文章让我了解了 90% 的情况。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:\SolutionPath\IisWebAppName\src\MyProjectName\obj\Release_Deploy\Package\PackageTmp" managedRuntimeVersion="v4.0" />
  <setAcl path="C:\SolutionPath\IisWebAppName\src\MyProjectName\obj\Release_Deploy\Package\PackageTmp" setAclResourceType="Directory" />
  <setAcl path="C:\SolutionPath\IisWebAppName\src\MyProjectName\obj\Release_Deploy\Package\PackageTmp" setAclUser="anonymousAuthenticationUser" setAclResourceType="Directory" />
  <setAcl path="C:\SolutionPath\IisWebAppName\src\MyProjectName\obj\Release_Deploy\Package\PackageTmp\files" setAclResourceType="Directory" setAclAccess="Read,Write,Modify" />
</sitemanifest>

这实际上看起来是正确的,最后一行是我来自 wpp.targets 文件的自定义 ACL。但是,当 MSDeploy 将其发送到目标服务器时,会发生以下情况:

2>开始Web部署发布应用程序/包到https://webhostingprovider.biz:8172/msdeploy.axd?site=IisWebAppName ...
2>添加站点清单(sitemanifest)。
2>为路径添加ACL(IisWebAppName)
2>为路径添加ACL(IisWebAppName)
2>为路径添加ACL(C:\SolutionPath\IisWebAppname\src\MyProjectName\obj\Release_Deploy\Package\PackageTmp\files)
2>C:\Program Files (x86)\MSBuild\Microsoft\VisualStudio\v11.0\Web\Microsoft.Web.Publishing.targets(4377,5):错误ERROR_USER_NOT_AUTHORIZED_FOR_SETACL:Web部署任务失败。(使用 Web 管理服务连接时,无法使用指定的提供程序(“setAcl”)完成操作。如果服务器管理员未授权用户进行此操作,则可能会发生这种情况。setAcl http://go.microsoft.com/ fwlink/?LinkId=178034

整个事情都落在了我的自定义 ACL 路径上,该路径使用绝对路径名而不是相对于IisWebAppName。我不知道为什么!

请帮忙 :)

4

1 回答 1

1

您需要ProviderPath使用 a 创建一个参数,该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”(稍后在该答案中)的技巧,以将正则表达式转义的路径元数据添加到每个项目。

于 2012-10-17T10:40:20.067 回答