Adding Custom Files to an MSDeploy Package
As part of some of my web projects I have “plugin assemblies” that
aren’t directly referenced by the project but are things I want included
in my deployment package. I tried following the instructions on this
fairly popular blog
entry,
but it didn’t seem to work - that blog entry tells you to modify a set
of files during a stage in the packaging pipeline
“CopyAllFilesToSingleFolderForPackageDependsOn
” and that target never
actually fired for me. In fact, I threw an <Error> call in there just
to see if I could get the build to fail and… no luck.
It also seems that manually copying the files over into the deployment staging/temporary folder stopped working - you can copy them over, but they instantly get deleted just before packaging occurs.
Turns out a lot of the way the MSDeploy packaging stuff in
Microsoft.WebApplication.targets
works changed in Visual Studio 2012
and… it’s like no one out there noticed. Or maybe everyone solved the
problem and forgot to blog it. Or maybe I’m some special edge case.
Anyway, it took some serious reverse-walkthrough of the packaging
process to figure out what needs to happen. (Yeah, that was a day
wasted.)
Now, instead of “CopyAllFilesToSingleFolderForPackageDependsOn
” for
the event to handle, use
“PipelineCopyAllFilesToOneFolderForMsdeployDependsOn
” for including
your custom files. Once you do that, you don’t have to copy the files
into the staging area or anything; the packaging process will do that
for you.
Something else that changed - the “Package
” target in
Microsoft.WebApplication.targets
seems to rely on the “Build
” target
in some cases. I tried setting the property so “Package
” wouldn’t rely
on “Build
” (PipelineDependsOnBuild
) but it always ended up doing
some portion of “Build
.” The problem there is that “Build
“(from
Microsoft.Common.targets
) wants to run a target called
“IntermediateClean
” that deletes a bunch of stuff out of your bin
folder - even assemblies that were built due to project references.
(This happens more during a command line build than during a VS build.
They’re treated differently… which is pretty annoying.) What this means
is you have to “fool” the “IntermediateClean
” during the packaging
process so it doesn’t clean out your plugins. You do that by setting a
“magic” item called FileWrites
to contain all the stuff you want to
keep.
Here’s a snippet from my web project .csproj file showing how I just include everything in the bin folder since I want all the copied-in dependencies to be kept for the packaging:
<PropertyGroup>
<PipelineCopyAllFilesToOneFolderForMsdeployDependsOn>
IncludePluginFilesForMsdeploy;
$(PipelineCopyAllFilesToOneFolderForMsdeployDependsOn);
</PipelineCopyAllFilesToOneFolderForMsdeployDependsOn>
</PropertyGroup>
<Target Name="IncludePluginFilesForMsdeploy">
<ItemGroup>
<FileWrites Include="$(MSBuildProjectDirectory)\bin\**\*" />
<_CustomFiles Include="$(MSBuildProjectDirectory)\bin\**\*" />
<FilesForPackagingFromProject Include="%(_CustomFiles.Identity)">
<DestinationRelativePath>bin\%(RecursiveDir)%(Filename)%(Extension)</DestinationRelativePath>
</FilesForPackagingFromProject>
</ItemGroup>
</Target>
That all has to go after the line that imports the
Microsoft.WebApplication.targets
file.