4

I am trying to create publish profile which would copy all published files to various folders. Unfortunately I read that's not possible to do it directly through publishUrl and it's advised to publish to one folder from which to copy all the files. I managed to write the copy target functionality, but the order of when targets are run is wrong. I'm trying to run the publish directly from VisualStudio 2015, through Build > Publish Web.

Here is my publish profile:

<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <PropertyGroup>
    <WebPublishMethod>FileSystem</WebPublishMethod>
    <LastUsedBuildConfiguration>Debug</LastUsedBuildConfiguration>
    <LastUsedPlatform>Any CPU</LastUsedPlatform>
    <SiteUrlToLaunchAfterPublish />
    <LaunchSiteAfterPublish>False</LaunchSiteAfterPublish>
    <ExcludeApp_Data>True</ExcludeApp_Data>
    <publishUrl>obj\Package\PackageTemp</publishUrl>
    <DeleteExistingFiles>True</DeleteExistingFiles>
    <ExcludeFilesFromDeployment>Web.config;package.json;packages.config;Typescript\**;DynamicCss\**;gulpfile.js;</ExcludeFilesFromDeployment>
  </PropertyGroup>
  <Import Project="AdditionalResources.targets" />
  <PropertyGroup>
    <CopyAllFilesToSingleFolderForPackageDependsOn>AdditionalResources</CopyAllFilesToSingleFolderForPackageDependsOn>
  </PropertyGroup>
  <ItemGroup>
    <DestLocations Include="D:\PUBLISH_TEST\" />
    <DestLocations Include="D:\PUBLISH_TEST2\" />
  </ItemGroup>
  <Target Name="CopyToDeployFolders" AfterTargets="CopyAllFilesToSingleFolderForPackage" Outputs="%(DestLocations.Identity)">
    <ItemGroup>
      <PublishedFiles Include="obj\Package\PackageTemp\**\*" />
    </ItemGroup>
    <Message Importance="high" Text="FilesToCopy: @(PublishedFiles)" />
    <PropertyGroup>
      <_DeployPathIdentity>%(DestLocations.Identity)</_DeployPathIdentity>
    </PropertyGroup>
    <Copy SourceFiles="@(PublishedFiles)" DestinationFiles="@(PublishedFiles->'$(_DeployPathIdentity)%(RecursiveDir)%(Filename)%(Extension)')" />
  </Target>
</Project>

The order in which it's run is as follows:

Build
AdditionalResources
CopyToDeployFolders
Publish folder

Which is problematic, because my temp folder is not yet created/published. I tried to make my CopyToDeployFolders Target to override AfterPublish and tried to use various different AfterTargets, but none of them worked - sometimes my target was not executed or is run still before publish folder.

I tried to found out which target is run by looking at c:\Program Files (x86)\MSBuild\Microsoft\VisualStudio\v14.0\Web\Microsoft.Web.Publishing.targets as indicated by this answer Why does MSBuild ignore my BeforePublish target?, but didn't find the correct one, tried to changed AfterTarget to different ones, but the results are still the same.

Edit: Output with Diagnostic level:

2>    Target "GatherAllFilesToPublish" in file "C:\Program Files (x86)\MSBuild\Microsoft\VisualStudio\v14.0\Web\Microsoft.Web.Publishing.targets" from project "C:\MyProject\MySite\MySite.csproj" (entry point):
2>        Done building target "GatherAllFilesToPublish" in project "MySite.csproj".
2>Done building project "MySite.csproj".
2>Deleting existing files...
2>Publishing folder /...
... files being published ...
2>Web App was published successfully file:///C:/MyProject/MySite/MySite/obj/Package/PackageTemp
2>

Edit2: Added content of AdditionalResources.targets

<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <Target Name="AdditionalResources">
    <ItemGroup>
      <AddFiles Include="$(ProjectDir)\App_Themes\**\Basic\Dynamic.css">
        <CustomPath>App_themes\</CustomPath>
      </AddFiles>
      <AddFiles Include="C:\y\SharedDLL\Clients\Web\bin\**\*.dll">
        <CustomPath>bin\</CustomPath>
      </AddFiles>
      <AddFiles Include="C:\y\SharedDLL\Clients\Web\resources\**\ctrl_res\**\*.*" />
      <AddFiles Include="C:\y\SharedDLL\Clients\Web\resources\js\**\*.*">
        <CustomPath>js\</CustomPath>
      </AddFiles>
      <AddFiles Include="C:\y\SharedDLL\Clients\Web\resources\**\ClientBin\**\*.xap" />
      <AddFiles Include="C:\y\SharedDLL\Clients\Web\resources\FileUpload\**\*.js">
        <CustomPath>js\</CustomPath>
      </AddFiles>
      <!-- Minified files should be copied last to override non-minified ones -->
      <AddFiles Include="$(ProjectDir)\MINIFIED_FILES\**\*.*" />
    </ItemGroup>
    <ItemGroup>
      <FilesForPackagingFromProject Include="%(AddFiles.Identity)">
        <DestinationRelativePath>%(AddFiles.CustomPath)%(RecursiveDir)%(Filename)%(Extension)</DestinationRelativePath>
      </FilesForPackagingFromProject>
    </ItemGroup>
  </Target>
</Project>
CrudaLilium
  • 654
  • 7
  • 18
  • Run with msbuild verbosity set to diagnostic, it will show all targets, then just pick the appropriate one to use with AfterTargets. – stijn Aug 09 '17 at 07:07
  • @stijn Tried that, but there are no targets when the files start being published. Updated my question without output. – CrudaLilium Aug 09 '17 at 07:46
  • @CrudaLilium, I created a sample with your publish profile, after test I found that the target CopyToDeployFolders was executed after publish (I comment the target AdditionalResources, because I did not have AdditionalResources.targets file). So would you mind sharing us the AdditionalResources.targets file or test sample by onedrive, share the link here, so that we could reproduce this issue. – Leo Liu Aug 09 '17 at 09:50
  • @Leo-MSFT Updated my question with content of AdditionalResources.targets since it's not too big, it should add additional files that are not part of the project, but are necessary for the site. I didn't include it because I think it is irrelevant to the problem, I'll try to remove it and publish again to see if it's affecting the order. – CrudaLilium Aug 09 '17 at 11:40
  • Commented out import and use of AdditionalResources target, as well as Changing AfterTarget to "CopyToDeployFolders", but the order is still same. It seems all my targets are run inside GatherAllFilesToPublish target, CopyToDeployFolders is also part of it, but files are published after it. – CrudaLilium Aug 09 '17 at 11:53

1 Answers1

7

I tried to make my CopyToDeployFolders Target to override AfterPublish and tried to use various different AfterTargets, but none of them worked

After test the project file with with msbuild verbosity set to detail. I got the same result as you. Then I found that the custom target CopyToDeployFolders was executed after copy file to obj\Release\Package\PackageTmp but before Publishing folder. Just as the order that you got.

Build
AdditionalResources
CopyToDeployFolders
Publish folder

After further investigation, I found a official response:

"We currently do not support executing custom targets after publish from VS for the file system protocol. If you publish from the command line the target will be executed however."

Besides, just as we saw the log in output window, the custom target CopyToDeployFolders was executed after copy file to obj\Release\Package\PackageTmp. As a workaround, you can copy all the files from the folder "obj\Release\Package\PackageTmp" rather than the publish folder "obj\Package\PackageTemp", then the problem is solved.

So just need to change <PublishedFiles Include="obj\Package\PackageTemp\**\*" /> to:

<ItemGroup>
  <PublishedFiles Include="obj\Debug\Package\PackageTmp\**\*" />
</ItemGroup>
Leo Liu
  • 71,098
  • 10
  • 114
  • 135
  • Thanks for the workaround, it works and it's great since I need it to run from VS. Also tried to run from console and it is indeed run after publish, but since we are trying to get rid of many batchfiles I'll go with the workaround. – CrudaLilium Aug 10 '17 at 06:59