【问题标题】:Can Web Deploy's setAcl provider be used on a sub-directory?可以在子目录上使用 Web Deploy 的 setAcl 提供程序吗?
【发布时间】:2011-10-15 06:35:57
【问题描述】:

我正在尝试使 MS Deploy 包中的子目录对应用程序池用户可写。多亏了 Kevin Leetham 的 helpful post about the setAcl provider,我才能够将我需要的大部分内容放入我的项目文件中:

<MsDeploySourceManifest Include="setAcl"
                        Condition="$(IncludeSetAclProviderOnDestination)">
  <Path>$(_MSDeployDirPath_FullPath)\doc\public</Path>
  <setAclAccess>Read,Write,Modify</setAclAccess>
  <setAclResourceType>Directory</setAclResourceType>
  <AdditionalProviderSettings>setAclResourceType;setAclAccess</AdditionalProviderSettings>
</MsDeploySourceManifest>

请注意,我已将“\doc\public”添加到根部署目录。在 VS2010 构建的结果清单中,我看到了以下 setAcl 元素:

<sitemanifest>
  <contentPath path="C:\Source\...\obj\Debug\Package\PackageTmp" />
  <setAcl path="C:\Source\...\obj\Debug\Package\PackageTmp"
          setAclResourceType="Directory" />
  <setAcl path="C:\Source\...\obj\Debug\Package\PackageTmp"
          setAclUser="anonymousAuthenticationUser"
          setAclResourceType="Directory" />
  <setAcl path="C:\Source\...\obj\Debug\Package\PackageTmp\doc\public"
          setAclResourceType="Directory"
          setAclAccess="Read,Write,Modify" />
</sitemanifest>

最后一行看起来不错:它附加了我想要可写的子目录,并且访问修饰符似乎都已经足够好地转移了。

但是,当我部署这个包时,我收到一个错误:

错误:必须指定“setAclUser”设置的值,当 'setAcl' 提供程序与物理路径一起使用。

这是一个令人困惑的错误,因为我并没有尝试在物理路径上设置 ACL,确切地说,而是 Web 应用程序的子目录。查看 MS Deploy 的输出,很容易看出问题所在:

Info: Adding setAcl (REST Services\1.0.334).
Info: Adding setAcl (REST Services\1.0.334).
Info: Adding setAcl (C:\...\obj\Release\Package\PackageTmp\doc\public).

MS Deploy 显然将 Web 应用程序名称替换为我的绝对路径“C:...\obj\Release\Package\PackageTmp”,但是当我将“\doc\public”附加到该绝对路径时,它不再识别它作为一个 Web 应用程序目录。另一个受害者 over on the ASP.NET forums 描述了这个确切的问题,但没有任何解决方案。

有谁知道如何通过 Web Deploy 在 Web 应用程序的特定子目录上设置 ACL,而无需手动识别目标主机上的物理路径和应用程序池用户?

【问题讨论】:

    标签: visual-studio-2010 iis-7 msdeploy webdeploy


    【解决方案1】:

    好吧,让我先说这比它应该的要难!

    我认为它失败的原因是因为当您发布它时,它无法将该文件夹识别为 IIS 应用程序中的文件夹。发生这种情况的原因是,当调用 SetAcl 提供程序时,完整路径正在传输到目的地。取而代之的是,我们需要一个相对于 IIS 应用程序的路径。例如,在您的情况下,它应该类似于:“REST SERVICES/1.0.334/doc/public”。执行此操作的唯一方法是创建一个 MSDeploy 参数,该参数在发布时填充正确的值。除了在源清单中创建自己的 SetAcl 条目之外,您还必须执行此操作。请按照以下步骤操作。

    1. 在与您的项目相同的目录中创建一个名为 {ProjectName}.wpp.targets 的文件(其中 {ProjectName} 是您的 Web 应用程序项目的名称)
    2. 在文件中粘贴此列表下方的 MSBuild 内容
    3. 在 Visual Studio 中重新加载项目(VS 将项目文件缓存在内存中,因此需要清除此缓存)。

    {ProjectName}.wpp.targets

    <?xml version="1.0" encoding="utf-8"?>
    <Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
    
      <Target Name="SetupCustomAcls" AfterTargets="AddIisSettingAndFileContentsToSourceManifest">   
        <!-- This must be declared inside of a target because the property 
        $(_MSDeployDirPath_FullPath) will not be defined at that time. -->
        <ItemGroup>
          <MsDeploySourceManifest Include="setAcl">
            <Path>$(_MSDeployDirPath_FullPath)\doc\public</Path>
            <setAclAccess>Read,Write,Modify</setAclAccess>
            <setAclResourceType>Directory</setAclResourceType>
            <AdditionalProviderSettings>setAclResourceType;setAclAccess</AdditionalProviderSettings>
          </MsDeploySourceManifest>
        </ItemGroup>
      </Target>
    
      <Target Name="DeclareCustomParameters" AfterTargets="AddIisAndContentDeclareParametersItems">
        <!-- This must be declared inside of a target because the property 
        $(_EscapeRegEx_MSDeployDirPath) will not be defined at that time. -->
        <ItemGroup>
          <MsDeployDeclareParameters Include="DocPublicSetAclParam">
            <Kind>ProviderPath</Kind>
            <Scope>setAcl</Scope>
            <Match>^$(_EscapeRegEx_MSDeployDirPath)\\doc\\public$</Match>
            <Value>$(_DestinationContentPath)/doc/public</Value>
            <ExcludeFromSetParameter>True</ExcludeFromSetParameter>
          </MsDeployDeclareParameters>
        </ItemGroup>
      </Target>
    
    </Project>
    

    稍微解释一下,目标 SetupCustomAcl 将导致一个新的 SetAcl 条目放置在发布期间使用的源清单中。该目标在 AddIisSettingAndFileContentsToSourceManifest 目标执行后通过 AfterTargets 属性执行。我们这样做是为了确保在正确的时间创建项目值,并且因为我们需要确保填充属性 _MSDeployDirPath_FullPath

    DeclareCustomParameters 是创建自定义 MSDeploy 参数的位置。该目标将在 AddIisAndContentDeclareParametersItems 目标之后执行。我们这样做是为了确保填充属性 _EscapeRegEx_MSDeployDirPath。请注意,当我声明参数的值时(在 Value 元素内)我使用属性 _DestinationContentPath 时在该目标内部,该属性是 MSBuild 属性,其中包含您的应用程序正在部署的路径,即 REST 服务/1.0.334.

    您可以尝试一下并告诉我它是否适合您吗?

    【讨论】:

    • 嘿,我一点也不觉得自己没有弄清楚这一点而感到难过。不过,它确实有效,我很感谢您抽出时间来创建如此全面的答案!
    • 有没有办法让它适用于多个文件夹?例如,您将如何扩展它以使 doc/public 不仅可写,而且 /home/temp
    • 您应该能够只复制 MSDeploySourceManifest 和 MSDeployDeclareParameters 的项目值并更新值。你试过了吗,它没有用
    • 仅供参考 - 例如,这似乎不适用于未推送到虚拟目录并推送到 Default Site/ 的应用程序。我正在尝试弄清楚如何对其进行调整,以便它也适用于这种情况。错误位于调用 VSMSDeploy 的 Web.Publishing.targets 的第 3847 行 - 站点“不存在”。
    • 这可能是一个错误,你能把详细信息发邮件给我,以便我跟进吗?我的电子邮件是 sayedha [at]{Microsoft}dotCOM.
    【解决方案2】:

    仅供参考 - 如果您遵循此处帖子中指定的约定,这确实适用于根网站: http://forums.iis.net/p/1176955/1977169.aspx#1977169

    <Match>^$(_EscapeRegEx_MSDeployDirPath)\\@(CustomDirAcl)$</Match>
    <DefaultValue>{$(_MsDeployParameterNameForContentPath)}/@(CustomDirAcl)</DefaultValue>
    <Value>$(_DestinationContentPath)/@(CustomDirAcl)</Value>
    

    这篇文章还具有能够在单个 ItemGroup 中指定子目录块的好处。

    【讨论】:

    • 使用DefaultValue 从现有参数继承值使得这个答案更可取。
    猜你喜欢
    • 1970-01-01
    • 2010-12-23
    • 2011-09-23
    • 2015-09-18
    • 2018-10-11
    • 1970-01-01
    • 2017-01-06
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多