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
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
Now, instead of "
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
Something else that changed - the "
Package" target in
Microsoft.WebApplication.targets seems to rely on the "
in some cases. I tried setting the property so "
Package" wouldn't rely
PipelineDependsOnBuild) but it always ended up doing
some portion of "
Build." The problem there is that "
Microsoft.Common.targets) wants to run a target called
IntermediateClean" that deletes a bunch of stuff out of your
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
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