I have dynamically loaded plugin libraries that I'd like to push to running web host with new build while in development. To avoid "file in use" error on copy I create app_offline.htm
using msbuild in csproj to recycle the web app.
<ItemGroup>
<ModuleFiles Include="$(TargetDir)*.dll" />
</ItemGroup>
<Target Name="PublishModule" AfterTargets="PostBuildEvent">
<WriteLinesToFile File="$(SolutionDir)src\FooBar.Web.Mvc\app_offline.htm" />
<Copy SourceFiles="@(ModuleFiles)" DestinationFolder="$(SolutionDir)src\FooBar.Web.Mvc\Modules\FooBar.Blog\" SkipUnchangedFiles="true" />
<Delete Files="$(SolutionDir)src\FooBar.Web.Mvc\app_offline.htm" />
</Target>
It works as expected, but I'm wondering if it can be improved by wrapping PublishModule
target to only execute when output is changed. So If I build plugin that didn't change it won't unnecessarily recycle the web host. SkipUnchangedFiles
prevents any unchanged DLLs from being copied, but app_offline
is still created.
I need something like this, but it doesn't seem to do anything.
<RunPostBuildEvent>OnOutputUpdated</RunPostBuildEvent>
You can make your target incremental so it only builds when the inputs change or the expected outputs are missing:
<ItemGroup>
<ModuleFiles Include="$(TargetDir)*.dll" DestinationPath="$(SolutionDir)src\FooBar.Web.Mvc\Modules\FooBar.Blog\%(Filename)%(Extension)" />
</ItemGroup>
<Target Name="PublishModule" AfterTargets="PostBuildEvent" Inputs="@(ModuleFiles)" Outputs="@(ModuleFiles->'%(DestinationPath)')">
<WriteLinesToFile File="$(SolutionDir)src\FooBar.Web.Mvc\app_offline.htm" />
<Copy SourceFiles="@(ModuleFiles)" DestinationFiles="@(ModuleFiles->'%(DestinationPath)')"/>
<Delete Files="$(SolutionDir)src\FooBar.Web.Mvc\app_offline.htm" />
</Target>
See How to: Build Incrementally for details on incremental builds.