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

时间:2017-07-20 16:18:11

标签: visual-studio msbuild visual-studio-2017 microsoft-web-deploy

我在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>

2 个答案:

答案 0 :(得分:1)

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

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

  1. 我的解决方案目录
  2. 我们正在部署应用程序的路径。
  3. 最棒的是我可以登记我的.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
    

答案 1 :(得分:0)

  

我错过了我在胜利部署到我想要的位置的技巧。我哪里错了?或者这不可能吗?

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

众所周知,\**\*.*有助于从所有文件夹中获取文件。 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>