发布配置文件复制文件到相关目的地

Publish Profile Copy Files To Relative Destination

我在 visual studio 2017 中有一个发布配置文件 我正在尝试从另一个项目复制文件。转到简单的相对目录时这样做没有问题。但是,源代码中的双重递归存在问题,这使得确定所需目录变得更加困难。

源目录:$(MSBuildThisFileDirectory)..\..\..\..Foundation\**\App_Config\**\* 获取相关文件。

前往:<DestinationRelativePath /> 使用 %(RecursiveDir)%(Filename)%(Extension)

部署到:\**\App_Config\**\*

不合我意:\App_Config\**\*

我错过了我在 <DestinationRelativePath> 中放置的任何东西都不会部署到我想要的位置的技巧。我哪里错了?或者这是不可能的?

<PropertyGroup>      
    <PipelineCollectFilesPhaseDependsOn>
        GetFoundationConfigFiles;
        GetProjectConfigFiles;
        $(PipelineCollectFilesPhaseDependsOn);
    </PipelineCollectFilesPhaseDependsOn>
</PropertyGroup>

<Target Name="GetFoundationConfigFiles">
    <Message Text="Inside of GetFoundationConfigFiles" Importance="high"/>
    <ItemGroup>
        <_CustomFiles Include="$(MSBuildThisFileDirectory)..\..\..\..\Foundation\**\App_Config\**\*" />
        <FilesForPackagingFromProject Include="%(_CustomFiles.Identity)">
            <DestinationRelativePath>App_Config\Include\%(Filename)%(Extension)</DestinationRelativePath>
        </FilesForPackagingFromProject>
    </ItemGroup>
</Target>

<Target Name="GetProjectConfigFiles">
    <Message Text="Inside of GetProjectConfigFiles" Importance="high"/>
    <ItemGroup>
        <_CustomFiles1 Include="$(MSBuildThisFileDirectory)..\..\..\..\Feature\**\App_Config\**\*" />
        <FilesForPackagingFromProject Include="%(_CustomFiles1.Identity)">
            <DestinationRelativePath>%(RecursiveDir)%(Filename)%(Extension)</DestinationRelativePath>
        </FilesForPackagingFromProject>
    </ItemGroup>
</Target>

I am missing the trick what ever I place in the won't deploy to my desired location. Where am I going wrong? Or is this not possible?

在内部双重递归中使用过滤器和合并似乎是不可能的。

众所周知,\**\*.*有助于从所有文件夹中获取文件。 RecursiveDir 帮助将所有文件放在各自的文件夹中。当您使用 **\App_Config\** 从所有父文件夹和子文件夹中获取文件时, RecursiveDir 将通过双重递归将所有文件放入各自的文件夹(父文件夹和子文件夹)中。我们无法在递归过程中插入过滤器和合并。我们能做的是将所有这些文件发布到一个文件夹中:

<Target Name="GetProjectConfigFiles">
<Message Text="Inside of GetProjectConfigFiles" Importance="high"/>
<ItemGroup>
    <_CustomFiles1 Include="$(MSBuildThisFileDirectory)..\..\..\..\Feature\**\App_Config\**\*" />
    <FilesForPackagingFromProject Include="%(_CustomFiles1.Identity)">
        <DestinationRelativePath>App_Config%(RecursiveDir)%(Filename)%(Extension)</DestinationRelativePath>
    </FilesForPackagingFromProject>
</ItemGroup>

不确定这个结果是不是你想要的,如果你想获取所有没有父文件夹的文件,看起来你应该在获取所有文件时指定父文件夹:

<Target Name="GetFoundationConfigFiles">
<Message Text="Inside of GetFoundationConfigFiles" Importance="high"/>
<ItemGroup>
    <_CustomFiles Include="$(MSBuildThisFileDirectory)..\..\..\..\Foundation\Test1\App_Config\**\*" />        
    <FilesForPackagingFromProject Include="%(_CustomFiles.Identity)">
      <DestinationRelativePath>App_Config%(RecursiveDir)%(Filename)%(Extension)</DestinationRelativePath>
    </FilesForPackagingFromProject>
</ItemGroup>

决定执行 Powershell 是最好的选择。我没有进行 Web 部署,而是在 Visual Studio 2017 年切换到文件系统发布。

我使用发布配置文件执行 powershell 脚本并传递两个参数。

  1. 我的解决方案目录
  2. 我们也在部署应用程序的路径。

很棒的是我可以签入我的 .pubxml 并使用未签入文件的 .pubxml.user 来定义 2)。这允许每个开发人员在本地使用相同的发布配置文件。

如果有人知道如何在发布配置文件中使用自定义变量那就太好了,目前调用命令时仅限于传递我们从发布配置文件中获得的内容。

发布配置文件 .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 https://go.microsoft.com/fwlink/?LinkID=208121. 
-->
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <PropertyGroup>
    <WebPublishMethod>FileSystem</WebPublishMethod>
    <PublishProvider>FileSystem</PublishProvider>
    <LastUsedBuildConfiguration>Debug</LastUsedBuildConfiguration>
    <LastUsedPlatform>Any CPU</LastUsedPlatform>
    <SiteUrlToLaunchAfterPublish />
    <LaunchSiteAfterPublish>True</LaunchSiteAfterPublish>
    <ExcludeApp_Data>False</ExcludeApp_Data>
    <DeleteExistingFiles>False</DeleteExistingFiles>
    <PipelineDependsOn>
      CopyAssets;
      $(PipelineDependsOn);
    </PipelineDependsOn>
  </PropertyGroup>
  <Target Name="CopyAssets">
    <Message Text="Inside of CopyAssets" Importance="high"/>
    <Exec Command="%WINDIR%\System32\WindowsPowerShell\v1.0\powershell.exe -File &quot;$(SolutionDir)Foundation\Scripts\Powershell\CopyAssets.ps1&quot; $(SolutionDir) $(publishUrl)"/>
  </Target>
</Project>

发布个人资料。pubxml.user

<?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 https://go.microsoft.com/fwlink/?LinkID=208121. 
-->
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <PropertyGroup>
    <TimeStampOfAssociatedLegacyPublishXmlFile />
    <_NewBackgroundProfile>False</_NewBackgroundProfile>
    <_PublishTargetUrl>C:\inetpub\wwwroot\mywebapp</_PublishTargetUrl>
  </PropertyGroup>
</Project>

CopyAssets.ps1

#
# CopyAssets.ps1
#
[CmdletBinding()]
Param(
    [Parameter(Mandatory=$True)]
    [string]$solutionDirectory,

    [Parameter(Mandatory=$True)]
    [string]$copyTo
)

#
# Copy Assets Initializations
#
# Absolute path to copy files to and create folders in
$absolutePath = @($copyTo + "/App_Config/Include")
# Set paths we will be copy files from
$featureDirectory = Join-Path $solutionDirectory "/Feature/*/App_Config/Include"
$foundationDirectory = Join-Path $solutionDirectory "/Foundation/*/App_Config/Include"

function Create-Files {
    Param ([string]$currentPath, [string]$pathTo)
    Write-Host "Attempting to create files..."
    # Copy files from root include folder
    $files = Get-ChildItem -Path $currentPath | Where-Object {$_.PSIsContainer -eq $false}

    foreach ($file in $files)
    {
        Write-Host "Attempting to copy file:"$file "to"$path
        New-Item -ItemType File -Path $pathTo -Name $file.Name -Force
    }
}

# Logic to create new directories and copy files over.
function Copy-Assets {

    Param ([string]$directoryBase)
    $path = $absolutePath
    Write-Host "Directory copying from:" $directoryBase
    Write-Host "Creating files found in include folder"
    # Path hack to copy files from directoryBase
    $directoryBaseHack = Join-Path $directoryBase "\*"
    Create-Files -currentPath $directoryBaseHack -pathTo $path
    Write-Host "Getting sub directories to copy from"
    $directories = Get-ChildItem -Path $directoryBase -Recurse | Where-Object {$_.PSIsContainer -eq $true}
    Write-Host "Iterating through directories"
    foreach ($directory in $directories)
    {
        Write-Host "Checking if directory"$directory.Name "is part of absolute path."
        if($absolutePath -match $directory.Name)
        {
            # checking if directory already exists
            Write-Host "Directory is part of absolute path, confirming if path exists"
            $alreadyExists = Test-Path $absolutePath
            if(!$alreadyExists)
            {       
                Write-Host "Absolute path doesn't exist creating..."
                New-Item -ItemType Directory -Path $absolutePath -Force
                Write-Host "All directories in path for Absolute Path created:"$absolutePath
            }
            Write-Host "Directory for"$directory.Name "already exists as it is part of the Absolute Path:" $absolutePath
        }else{
            Write-Host "Joining path with absolute path"
            $path = Join-Path $absolutePath $directory.Name
            Write-Host "Joined path:"$path

            Write-Host "Does joined path exist:"$path
            $alreadyExists = Test-Path $path
            if(!$alreadyExists)
            {       
                Write-Host "Joined path doesn't exist creating..."
                New-Item -ItemType Directory -Path $path -Force
                Write-Host "Created new directory:" $path
            }
            Write-Host "Directory for"$path "already exists."
        }
        Write-Host "Creating files found in:" $directory
        Create-Files -currentPath $directory -pathTo $path
    }
}
Write-Host "Starting Copying Foundation Files"
Copy-Assets -directoryBase $foundationDirectory
Write-Host "Starting Copying Feature Files"
Copy-Assets -directoryBase $featureDirectory