Visual studio 将配置文件复制文件发布到相对目标

Visual studio 将配置文件复制文件发布到相对目标,visual-studio,msbuild,visual-studio-2017,microsoft-web-deploy,Visual Studio,Msbuild,Visual Studio 2017,Microsoft Web Deploy,我在visual studio 2017中有一个发布配置文件我正在尝试从另一个项目复制文件。当转到简单的相对目录时,这样做没有问题。但是,在源代码中进行的双重递归有一个问题,这使得确定所需的目录变得更加困难 源目录:$(MSBuildThisFileDirectory)\..\..\\..Foundation\***\App\u Config\***获取相关文件 转到:使用%(递归目录)%(文件名)%(扩展名) 它部署到:\***\App\u Config\*** 不符合我的要求:\App\u

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

源目录:
$(MSBuildThisFileDirectory)\..\..\\..Foundation\***\App\u Config\***
获取相关文件

转到:
使用
%(递归目录)%(文件名)%(扩展名)

它部署到:
\***\App\u Config\***

不符合我的要求:
\App\u Config\***

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

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

GetFoundationConfigFiles;
获取项目配置文件;
$(PipelineCollectFilesPhaseDependsOn);
应用程序配置\包括\%(文件名)%(扩展名)
%(RecursiveDir)%(文件名)%(扩展名)
我错过了一个诀窍,我在中放置的任何东西都不会部署到我想要的位置。我哪里做错了?或者这是不可能的

<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>
看起来不可能在内部双递归中使用过滤器和合并

众所周知,
\***.
帮助从所有文件夹中获取文件
RecursiveDir
帮助将所有文件放在相应的文件夹中。当您使用
**\App\u 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脚本,并将两个参数传递给它

  • 我的解决方案目录
  • 我们也正在部署应用程序的路径 最棒的是我可以签入我的.pubxml并使用未签入文件的.pubxml.user来定义2)。这允许每个开发人员在本地使用相同的发布配置文件

    如果有人知道如何在发布配置文件中使用自定义变量,那就太好了,只需在调用命令时传递发布配置文件中的变量

    Publish Profile.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>
    

    是的,第二个给了我我想要的,但可能有x个项目希望我能做到,而不必再添加其他工作来复制文件。有没有其他方法可以让你知道?我不受约束。我将尝试使用powershell实现这一点。我可以做更多的事情,我可以传递所需的任何参数,但移动相关文件的繁重工作现在可以在powershell中完成:)yaay@Anicho,很高兴知道您可以传递所需的任何参数。如果你能用PS解决这个问题,你可以在这里分享你的解决方案并将其标记为答案,这样对其他有同样问题的社区是有益的。PS是一个很酷的工具,在你提到它之前,我没有想过它。谢谢。得到了我想要的:)
    #
    # 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