【问题标题】:How do I get msdeploy to create App_Data if it doesn't exist, but not delete any contents of the remote directory?如果不存在,如何让 msdeploy 创建 App_Data,但不删除远程目录的任何内容?
【发布时间】:2012-01-17 18:50:26
【问题描述】:

我有一个具有以下打包/发布 Web 设置的应用程序设置:

  • 仅运行此应用程序所需的文件
  • (未选中)排除生成的调试符号
  • (选中)从 App_Data 文件夹中排除文件
  • (选中)包括在“打包/发布 SQL”选项卡中配置的所有数据库 - 注意我确实没有配置了任何数据库
  • (未选中)包括在 IIS Express 中配置的 IIS 设置

在项目中,我设置了一个 App_Data 文件夹,主要用于处理应用程序日志。

我希望看到(并期望)的行为如下:

  1. 在初始部署到全新服务器时,会复制应用程序并创建 App_Data 文件夹,并为应用程序分配写入权限。
  2. 在后续部署中,App_Data 文件夹将被忽略,因为它已经存在,并且选中了“从 App_Data 文件夹中排除文件”。

但是,msdeploy 似乎没有执行第 1 步(如果我手动创建文件夹,第 2 步很好)。除了这个 unanswered so question 之外,我在网上找不到任何文档,这似乎证实了我看到的行为。

在这种情况下,如何让 msdeploy 创建 App_Data 并为初始部署分配权限?

【问题讨论】:

    标签: asp.net .net msdeploy


    【解决方案1】:

    从头开始部署 App_Data

    @tdykstra 得到了this part right。为了获取 App_Data(并自动设置 ACL),我执行了以下操作:

    1. 在 App_Data 中添加占位符文件
    2. 将构建操作设置为占位符上的内容(我的占位符文件中有文本,让偶然发现它的人知道它为什么存在)。
    3. 未选中“从 App_Data 文件夹中排除文件”在 VS 2010 中项目属性的“打包/发布 Web”选项卡上

    这将创建我的 App_Data 文件夹并准备好在服务器上使用。但是,每当我重新发布时,它都会导致我的所有文件都被删除。这是我上面的问题中的问题 #2,与其他 SO question/answer 非常相似。

    防止服务器上的数据在后续发布事件中被删除

    MsDeploy 中有两种机制会让人感到困惑(至少我把它们弄糊涂了):

    1. 排除文件
    2. MsDeploy 跳过规则

    这些都可以用来解决问题,具体取决于场景:

    1. 如果您满足以下条件,@tdykstra's solution 可能会起作用:
      1. 提前知道 App_Data 中文件的名称(例如 sqllite 数据库)
      2. 将文件包含在项目的 App_Data 文件夹中
    2. 使用 MsDeploy 跳过规则告诉 MsDeploy 完全跳过服务器上对该目录和该目录中的文件的所有删除。这解决了所有情况下的问题,但涉及更多。

    实施 MsDeploy 跳过规则

    要实现跳过规则,您必须放弃 VS 2010 中的右键单击、部署选项,转而支持右键单击、打包、进入命令行、重新启动批处理文件并运行命令行) .如果您愿意忍受这种体验(我愿意,因为我通过 CI 流程将其全部自动化),以下是详细信息:

    1. Edit the project file and add the following。请注意,AbsolutePath 参数是一个正则表达式,所以你可以很花哨:

      <Target Name="AddCustomSkipRules">
          <ItemGroup>
            <MsDeploySkipRules Include="SkipDeleteAppData">
              <SkipAction>Delete</SkipAction>
              <ObjectName>filePath</ObjectName>
              <AbsolutePath>$(_Escaped_PackageTempDir)\\App_Data\\.*</AbsolutePath>
              <XPath>
              </XPath>
            </MsDeploySkipRules>
            <MsDeploySkipRules Include="SkipDeleteAppData">
              <SkipAction>Delete</SkipAction>
              <ObjectName>dirPath</ObjectName>
              <AbsolutePath>$(_Escaped_PackageTempDir)\\App_Data\\.*</AbsolutePath>
              <XPath>
              </XPath>
            </MsDeploySkipRules>
          </ItemGroup>
      </Target>
      
    2. 打包,不要部署项目。这将在目标目录中创建一个 zip 文件和 .cmd 文件(由 Package/Publish Web 选项卡上的“创建包的位置”定义)。默认情况下,这是 obj\Debug\Package(或 obj\Release\Package)
    3. 使用生成的命令文件部署站点

    在我的测试中,你必须打包并运行命令文件。项目文件调整将告诉 msbuild 将必要的 -skip 规则放入命令文件中。但是,直接从 VS 2010 doesn't seem to run the command file 使用“发布”功能(请参阅 this walkthrough 上的警告)...它直接调用 msdeploy 并且似乎不遵守项目文件跳过规则。我相信这是 VS 使用 msbuild -T:Package 和 msbuild -T:MsDeployPublish 构建项目的区别,但我没有对此进行测试。

    最后,命令文件不太正确,至少在 VS 2010 SP1 中是这样。 this SO answer 中有一个很好的错误描述,但基本上,VS(或者 /t:Package 目标是一个更好的罪魁祸首)设置命令文件以发布到机器而不指定站点。要解决这个问题,您需要以某种方式获取“?site=sitename”(可能是 ?site=Default+Web+Site,对于 https://machine 的完整 URL :8172/MsDeploy.axd?site=Default+Web+Site) 到 computerName 参数的末尾。

    我遇到的问题是命令文件(批处理文件)很难在命令行上使用 site= any,因为它错误地解析了命令行参数(即使转义)。除了直接修改 cmd 文件之外,我没有看到解决此问题的方法,但为了测试,我复制了我从失败的测试运行中看到的 msdeploy.exe 输出,并将其修改为在没有脚本的情况下直接调用 msdeploy.exe。

    现在它可以工作了,我打算将它应用到我的 CI 构建过程中。我将为最终解决方案做的是:

    1. 将我的构建脚本更改为使用 /T:Package(现在是 /T:MsDeploy)
    2. 让脚本搜索/替换例程更改生成的 cmd 部署脚本
    3. 运行修改后的部署脚本

    这真的应该更容易。

    更新

    这是我在 PowerShell 中提出的脚本搜索/替换例程:

    (Get-Content "project.deploy.cmd") 
      -replace('^set _ArgComputerName=$'
               ,"set  ArgComputerName=https://server:8172/MsDeploy.axd?Site=Default+Web+Site") 
      | Out-File -Encoding ascii deploy.cmd
    

    运行后,可以调用 deploy.cmd(不带 /M 选项),它将按预期工作。

    【讨论】:

    • 除非设置了 &lt;UseMSDeployExe&gt;true&lt;/UseMSDeployExe&gt;,否则使用 VS2017 和 MsDeploySkipRules 不会真正起作用。
    【解决方案2】:

    如果没有要复制的文件,Web Deploy 不会创建文件夹。您的方案中的一种解决方法是不使用 Exclude files from the App_Data folder 复选框,在 App_Data 中放置一个虚拟文件(例如其中没有任何内容的 .txt 文件),并指定文件排除App_Data 文件夹中的任何其他内容(例如 .sdf 文件)的规则。

    关于排除单个文件(您可以使用通配符),请参阅 MSDN 上部署常见问题解答中的第一个问题:

    http://msdn.microsoft.com/en-us/library/ee942158.aspx#can_i_exclude_specific_files_or_folders_from_deployment

    关于使用虚拟文件方法创建文件夹,请参阅本教程中的确保部署 Elmah 文件夹

    http://www.asp.net/web-forms/tutorials/deployment-to-a-hosting-provider/deployment-to-a-hosting-provider-configuring-project-properties-4-of-12

    【讨论】:

    • 这似乎应该可以工作,但我一直在搞砸一个小时,但没有成功。我可以完成第 1 部分,但文件/目录的排除不起作用,无论有没有通配符。我正在通过 CI 服务器构建,所以这可能是问题所在。我会在接下来的一两天内做更多的工作并报告。
    • 这种方法存在一个缺陷来解决 #2 - 在我的场景中,我想“排除”在构建时我不知道的文件(例如,滚动日志文件的日期为文件名)。为此,需要另一种方法。我将添加一个答案以进一步详细说明我的发现。
    • 您也可以使用通配符——因此如果您的日志文件都具有相同的扩展名,您可以排除所有具有该扩展名的文件。
    • 确实如此,但前提是您的项目文件确实知道日志文件。我在没有包含在项目中的日志文件的情况下对其进行了测试,它不起作用。 :(
    【解决方案3】:

    在 Visual Studio 中使用 Publish Web 对话框时,我设法让它工作。注意:它适用于任何文件夹,而不仅仅是App_Data

    这是基本的.pubxml 个人资料:

    <?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>
    <AfterAddIisSettingAndFileContentsToSourceManifest>AddCustomSkipRules</AfterAddIisSettingAndFileContentsToSourceManifest>
        <WebPublishMethod>MSDeploy</WebPublishMethod>
        <LastUsedBuildConfiguration>Local</LastUsedBuildConfiguration>
        <LastUsedPlatform>Any CPU</LastUsedPlatform>
        <SiteUrlToLaunchAfterPublish />
        <ExcludeApp_Data>False</ExcludeApp_Data>
        <MSDeployServiceURL>localhost</MSDeployServiceURL>
        <DeployIisAppPath>SuperCoolAwesomeAppName</DeployIisAppPath>
        <RemoteSitePhysicalPath />
        <SkipExtraFilesOnServer>False</SkipExtraFilesOnServer>
        <MSDeployPublishMethod>InProc</MSDeployPublishMethod>
        <EnableMSDeployBackup>False</EnableMSDeployBackup>
        <UserName />
        <_SavePWD>False</_SavePWD>
        <LaunchSiteAfterPublish>True</LaunchSiteAfterPublish>
      </PropertyGroup>
    
      <PropertyGroup>
        <UseMsDeployExe>true</UseMsDeployExe>
      </PropertyGroup>
    
      <Target Name="CreateEmptyFolders">
        <Message Text="Adding empty folders to Files" />
        <MakeDir Directories="$(_MSDeployDirPath_FullPath)\Files\Folder 1" />
        <MakeDir Directories="$(_MSDeployDirPath_FullPath)\Files\Folder 2" />
        <MakeDir Directories="$(_MSDeployDirPath_FullPath)\Files\Folder 3\Test"/>
      </Target>
    
      <Target Name="AddCustomSkipRules" DependsOnTargets="CreateEmptyFolders">
        <Message Text="Adding Custom Skip Rules" />
        <ItemGroup>
          <MsDeploySkipRules Include="SkipFilesInFilesFolder">
            <SkipAction>Delete</SkipAction>
            <ObjectName>filePath</ObjectName>
            <AbsolutePath>$(_DestinationContentPath)\\Files\\.*</AbsolutePath>
            <Apply>Destination</Apply>
          </MsDeploySkipRules>
    
          <MsDeploySkipRules Include="SkipFoldersInFilesFolders">
            <SkipAction></SkipAction>
            <ObjectName>dirPath</ObjectName>
            <AbsolutePath>$(_DestinationContentPath)\\Files\\.*\\*</AbsolutePath>
            <Apply>Destination</Apply>
          </MsDeploySkipRules>
    
        </ItemGroup>
      </Target>
    
    </Project>
    

    这里有一篇详细解释它的帖子:

    Using MsDeploy publish profile .pubxml to create an empty folder structure on IIS and skip deleting it with MsDeploySkipRules

    【讨论】:

      【解决方案4】:

      简明扼要地总结和简化 Emil 和 Leniel 的答案,如果您只想允许 App_Data deploy 进行添加和更新,但阻止删除,请将其添加到您的 .pubxml

      <Project>
        ...
      
        <PropertyGroup>
          <UseMSDeployExe>true</UseMSDeployExe>
          <ExcludeApp_Data>False</ExcludeApp_Data>
        </PropertyGroup>
      
        <Target Name="AddCustomSkipRules"
                AfterTargets="AddIisSettingAndFileContentsToSourceManifest">
          <Message Text="Adding Custom Skip Rules" />
          <ItemGroup>
            <MsDeploySkipRules Include="SkipDeleteAppData">
              <SkipAction>Delete</SkipAction>
              <ObjectName>filePath</ObjectName>
              <AbsolutePath>App_Data\\.*</AbsolutePath>
            </MsDeploySkipRules>
            <MsDeploySkipRules Include="SkipDeleteAppData">
              <SkipAction>Delete</SkipAction>
              <ObjectName>dirPath</ObjectName>
              <AbsolutePath>App_Data</AbsolutePath>
            </MsDeploySkipRules>
          </ItemGroup>
        </Target>
      </Project>
      

      &lt;UseMSDeployExe&gt;true&lt;/UseMSDeployExe&gt; 是真的需要,否则它会失败抱怨Unrecognized skip directive 'skipaction'

      【讨论】:

        猜你喜欢
        • 2014-06-24
        • 2012-10-01
        • 1970-01-01
        • 2019-02-28
        • 2011-05-16
        • 2011-02-26
        • 1970-01-01
        • 2023-04-02
        • 1970-01-01
        相关资源
        最近更新 更多