Web Deploy的setAcl提供程序可以在子目录上使用吗?

19

我正在尝试让MS Deploy包中的子目录对应用程序池用户可写。感谢Kevin Leetham在关于setAcl提供者的有用帖子,我能够将大部分需要的内容添加到我的项目文件中:

<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似乎将我的绝对路径“C:...\ obj \ Release \ Package \ PackageTmp”替换为Web应用程序名称,但是当我在该绝对路径后附加“\ doc \ public”时,它不再将其识别为Web应用程序目录。这个问题被另一个受害者描述得非常准确,在ASP.NET论坛上,但没有任何解决方法。

是否有人知道如何通过Web Deploy在不手动识别目标主机上的物理路径和应用程序池用户的情况下设置Web应用程序的特定子目录的ACL?

2个回答

19

首先,让我说这比它应该的难很多!

我认为它失败的原因是,在进行发布时,它无法将文件夹识别为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>
为了解释这个过程,目标 SetupCustomAcls 将会在发布过程中的源清单内添加一个新的 SetAcl 条目。该目标会在 AfterTargets 属性中指定的 AddIisSettingAndFileContentsToSourceManifest 目标执行后被执行。我们这样做是为了确保该项值在正确的时间被创建,并且因为我们需要确保属性 _MSDeployDirPath_FullPath 被填充。
DeclareCustomParameters 是创建自定义 MSDeploy 参数的地方。该目标会在 AddIisAndContentDeclareParametersItems 目标执行后被执行。我们这样做是为了确保属性 _EscapeRegEx_MSDeployDirPath 被填充。请注意,在该目标中我声明参数的值时(在 Value 元素内),我使用了属性 _DestinationContentPath,该属性包含你的应用程序正在部署的路径,即“REST Services/1.0.334”。
你可以尝试一下这样做,然后告诉我是否起作用了?

呵呵,我一点也不觉得自己没能独立解决这个问题有什么不好的。虽然如此,它确实有效,我很感激你花时间提供如此全面的答案! - ladenedge
有没有办法让它适用于多个文件夹?例如,如何扩展它,使得不仅doc/public可写,还有/home/temp - TimH
你应该可以直接复制MSDeploySourceManifest和MSDeployDeclareParameters的项目值并更新它们。你试过了吗?如果不行的话,请告诉我。 - Sayed Ibrahim Hashimi
3
FYI - 这似乎对那些未推送到虚拟目录且被推送到默认站点(例如Default Site/)的应用程序不起作用。我正在尝试调整它,以便它也适用于这种情况。错误出现在Web.Publishing.targets文件的第3847行,其中调用了VSMSDeploy - 站点“”不存在。 - Ethan J. Brown
这可能是一个错误,你能通过电子邮件向我发送详细信息,以便我跟进吗?我的电子邮件是sayedha[at]{Microsoft}dotCOM。 - Sayed Ibrahim Hashimi

3

请注意- 如果您按照此处指定的约定遵循根网站,则此方法适用于根网站: http://forums.iis.net/p/1176955/1977169.aspx#1977169

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

这篇文章的好处之一是可以在单个ItemGroup中指定一组子目录。


1
дҪҝз”ЁDefaultValueжқҘ继жүҝзҺ°жңүеҸӮж•°зҡ„еҖјдҪҝеҫ—иҝҷдёӘзӯ”жЎҲжӣҙеҠ еҸҜеҸ–гҖӮ - Richard Szalay

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接