Ignore file from delete during WebDeploy - visual-studio-2010

I'm using TeamCity to build and deploy a collection of MVC Applications via msbuild and WebDeploy.
In a step previous to my solution build/deploy, I copy an app_offline.htm to the deploy directory so that I can perform SQL updates and other web/solution management steps including the build.
One of the setting in the WebDeploy is to delete files that aren't included in the project, or not needed to run the site. This deletes my app_offline.htm file each time. While I understand this is kind of the desired result, is there a way to exclude this file from being deleted from the deployment directory upon the deploy?
I've tried adding an ItemGroup with the ExcludeFromPackageFiles option, with no results.

I had a similar problem, wanting to keep minified javascript files in the deployment package even though they're not part of the project.
I added a custom MSBuild target for this, that works for me:
<!-- ====== Package the minify files ===== -->
<PropertyGroup>
<CopyAllFilesToSingleFolderForPackageDependsOn>
CustomCollectFiles1;
$(CopyAllFilesToSingleFolderForPackageDependsOn);
</CopyAllFilesToSingleFolderForPackageDependsOn>
</PropertyGroup>
<PropertyGroup>
<AfterAddIisSettingAndFileContentsToSourceManifest>
MakeEmptyFolders
</AfterAddIisSettingAndFileContentsToSourceManifest>
</PropertyGroup>
<Target Name="CustomCollectFiles1">
<ItemGroup>
<!-- =====Controls\Javascript folder ==== -->
<_CustomFilesForRootFolder Include=".\Controls\Javascript\*.min.js">
<DestinationRelativePath>%(RecursiveDir)%(Filename)%(Extension) </DestinationRelativePath>
</_CustomFilesForRootFolder>
<FilesForPackagingFromProject Include="%(_CustomFilesForRootFolder.Identity)">
<DestinationRelativePath>.\Controls\Javascript\%(RecursiveDir)%(Filename)%(Extension)</DestinationRelativePath>
</FilesForPackagingFromProject>
</ItemGroup>
</Target>

This other question " Custom app_offline.htm file during publish " suggests one possible way for the final result you describe:
I use my own
app_offline.htm_
file in the solution, which gets
published. My deployment script then
renames it (removing the trailing _)
to make it active.
I can then run my db scripts/do
whatever then rename the file bringing
the site back.

Related

Include File in NuGet package on Build, only if it does not exist

A while ago I asked this question:
Including a Folder in NuGet Package and have it install into project as file .netcore/Razor
The answer to which has got me most of the way where I want to go, but the trouble is rebuilding or updating the NuGet package in my projects is now overwriting files that are user-editable.
I feel the answer is somewhere in the .props file but I am not sure how to achieve it:
<Project>
<Target Name="CopyFiles" BeforeTargets="Build" >
<ItemGroup>
<File Include="$(MSBuildThisFileDirectory)..\Pagesettings\*.*"></File>
</ItemGroup>
<Copy SourceFiles="#(File)" DestinationFolder="$(ProjectDir)Pagesettings"></Copy>
</Target>
</Project>
The Target tag has an optional attribute Condition. I am guessing that somehow this can be used...?
So, to clarify my question:
From my original question linked above I have a NuGet package which when downloaded creates a folder called PageSettings, into which is copied a bunch of default JSON files containing PageSettings from my NuGet package. NOTE; these files initially appear in Visual Studio as linked files. They are not actually copied to the directory until the project is built.
However, the purpose of these PageSettings files is to be a default , or if you like an example, of PageSettings for users of my NuGet package. Once installed, the user can and should change these .JSON files, so now when their project is rebuilt, or if there is an update to the NuGet package available which they install, these JSON files should NOT update/install.
Sure. My answer quite has some flaws. To prevent overwriting existing files and files that have changed, I suggest you use xcopy with /d. It will not overwrite the existing files.
Instead, use this in test.props file:
<Project>
<Target Name="CopyFiles" BeforeTargets="Build">
<ItemGroup>
<File Include="$(MSBuildThisFileDirectory)..\Pagesettings\*.*"></File>
</ItemGroup>
<Exec Command="xcopy /s/d/y #(File) $(ProjectDir)Pagesettings\"></Exec>
<!--<Copy SourceFiles="#(File)" DestinationFolder="$(PorojectDir)Pagesettings" Condition="!Exists('$(PorojectDir)Pagesettings\*.*')"></Copy>-->
</Target>
</Project>
Then, repack your nuget project. Before using this new one, please clean nuget caches first.

Build target in the Publish Profile is not executing even if the Publish is successful

I have a publish profile Staging.pubxml created for a console project (.NET Core 2.1), as follows:
<?xml version="1.0" encoding="utf-8"?>
<!--
https://go.microsoft.com/fwlink/?LinkID=208121.
-->
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<PublishProtocol>FileSystem</PublishProtocol>
<Configuration>Staging</Configuration>
<Platform>Any CPU</Platform>
<TargetFramework>netcoreapp2.1</TargetFramework>
<PublishDir>bin\Release\netcoreapp2.1\publish\</PublishDir>
<SelfContained>false</SelfContained>
<_IsPortable>true</_IsPortable>
</PropertyGroup>
<Target Name="CustomActionsAfterPublish" AfterTargets="AfterPublish">
<Message Text="First occurrence" Importance="high" />
</Target>
</Project>
When I publish it (via VS2019); publish completes successfully. Yet I'am not seeing the text: First occurrence in the output window.
In VS, MSBuild output verbosity is set to Diagnostic.
Am I doing this wrong?
Am I doing this wrong?
1.Hi friend, the .pubxml file is not a good place to define custom Target.
According to your target name, you want to run the target after build target. For this situation: always we define the custom target in project file. Please try right-click your project and choose edit xxx.csproj, and add the target into it. Then reload the project and publish, then you can find the First occurrence message in the build output.
And after my test, in.csproj file, the target can't be named AfterBuild, you can change it to:
<Target Name="CustomTargetName" AfterTargets="build">
<Message Text="First occurrence" Importance="high" />
</Target>
2.Also, the way you use can work in VS2019 though we don't suggest adding it in .pubxml. But it indeed works. For the reason why you can't get the message in output window, please check if the Staging.pubxml is really called during the publish process.
(Change the value of the PublishDir to another folder, and publish it again, check if the project is published to new directory, then you'll find if the xxx.pubxml is used)
Update:
According to your .pubxml file, your project is a .net core console app instead of a asp.net core web app. This makes the difference!
I test it in both VS2017 and VS2019, and find the target works well in asp.net web app but not .net core console one. I believe for those non-web app, this kind of after publish target may not be supported.
And please check these two official documents I found:
Asp.net core: Run a target before or after publishing
.net core: Deploy .net core apps with VS
I can't find any custom-target-related info in the .net core document. So I'm afraid it might be not supported by design.
Update2:
Actually your original need is to add CopyFiles target to publish process. So I assume what you really want is to copy sth to Publish Folder after Publish process or copy sth from Publish Folder to target folder.
Though the after publish target is not supported in .net core console apps. We have corresponding workarounds:
To copy sth to Publish Folder after Publish:
For this situation, you can add a after build target to copy the files to Publish folder before publish process. I think it works for this situation:
<Target Name="CustomTarget" AfterTargets="build">
<ItemGroup>
<MySourceFiles Include="xxx\pathToTheFolderWhereYourFilesAre\*.*"/>
</ItemGroup>
<Copy
SourceFiles="#(MySourceFiles)"
DestinationFolder="$(ProjectDir)bin\Release\netcoreapp2.1\publish\"
/>
</Target>
To copy sth from Publish Folder to target folder:
For .net core console app, actually the so-called publish process is to copy files from obj folder to publish folder. See this screenShot:
Go Tools=>Options=>Project and Solutions=>Build and Run to change the build output verbosity to Detailed and you can see details in build and publish process in VS.
That's why I suggest you can Go Project=>Properties=>build events=>post-build events to use a xcopy command to copy the files to your destination folder.(Or you can use a script like above, remember to change the source path and destination path). When we want to copy the files in publish folder, actually we're trying to copy the files from obj folder. So do something after build process is enough! Not need to do it after publish process.

How do I include webjob files while debugging locally but exclude when publishing a web package?

I'm using Visual Studio 2017 and have a solution with several web projects and webjob projects.
There are some files that I want to include when running locally in the development environment that I want to exclude from being deployed as part of a web publishing package.
I'm attempting to use the process described here http://sedodream.com/2010/05/01/WebDeploymentToolMSDeployBuildPackageIncludingExtraFilesOrExcludingSpecificFiles.aspx and elsewhere, which is:
<ItemGroup>
<ExcludeFromPackageFiles Include="connectionstrings.config">
<FromTarget>Project</FromTarget>
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</ExcludeFromPackageFiles>
</ItemGroup>
This works perfectly for my web projects - meaning that when building the connectionstrings.config file is copied to my bin\ directory and not included as part of the web deployment package - whereas when implemented in my webjob projects the file is copied to my bin\ directory but also included in the deployment package.
In the msbuild output I see:
Copying file from "C:\Users\me\Documents\Projects\myapp\myapp\webjob1\connectionstrings.config" to "bin\ProdBuildCfg\connectionstrings.config".
which is what I want because it allows me to run/debug locally, and also:
Copying C:\Users\me\Documents\Projects\myapp\myapp\webjob1\bin\ProdBuildCfg\connectionstrings.config to obj\ProdBuildCfg\Package\PackageTmp\app_data\jobs\continuous\webjob1\connectionstrings.config.
which demonstrates the problem - connectionstrings.config is still being copied to the package directory for subsequent publishing/deployment.
The process described in the above article and others applies to web projects, and they indicate you should place the <ItemGroup> under the
<Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v10.0\WebApplications\Microsoft.WebApplication.targets" />
line of the project file. Webjob projects don't include that line but rather have something resembling:
<Import Project="..\packages\Microsoft.Web.WebJobs.Publish.1.0.13\tools\webjobs.targets" Condition="Exists('..\packages\Microsoft.Web.WebJobs.Publish.1.0.13\tools\webjobs.targets')" />
I suspect the problem relates to targets - either my project file doesn't include the proper <Import Project="...*.targets')" /> line or I'm not at the right spot in the file.
Next I tried the method mentioned here How do I include webjob files while debugging locally but exclude when publishing a web package?:
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<ExcludeFilesFromDeployment>connectionstrings.config</ExcludeFilesFromDeployment>
</PropertyGroup>
I have the connectionstrings.config Build Action set to None and Copy to output directory set to Always (my understanding is that action that results from the Copy to output directory setting is distinctly different from the actions associated with packaging/deployment). Same result. (I've ensured I'm in the right <PropertyGroup> for my build configuration.
Note: I'm deploying either by right-clicking the project in VS and selecting "Publish as Azure webjob" or using an msbuild command to publish like msbuild myproj.csproj /p:DeployOnBuild=true /p:Configuration=Release /p:PublishProfile="Prod" /p:VisualStudioVersion=15.0 /p:Password=
How do I include webjob files while debugging locally but exclude when publishing a web package?
To my knowledge, if you do not want to publish any file, you just need to set the file property to "copy to output directory as DO NOT COPY". This way when you will package the application that particular file will not be part of package and will never be on Azure.
Update:
Unfortunately that setting prevents the file from being copied to the
output directory which means I can’t run or debug locally.
When you debugging the project, you can set the "copy to output directory" as "Copy always". When you want to deploy the project, you can manually clean the build and change the value to DO NOT COPY.
If you do not want to do all those manually, I would like provide you a workaround, hope this can help you.
To accomplish this, unload your project. Then at the very end of the project , just before the end-tag, place below scripts:
<Target Name="ExcludeFileFromPackage" BeforeTargets="PipelineCopyAllFilesToOneFolderForMsdeploy">
<Message Text="Delete the connectionstrings.config from Obj folder to exculde this file in the package directory" />
<Delete Files="$(ProjectDir)obj\Release\Package\PackageTmp\connectionstrings.config" />
</Target>
With this target, VS/MSBuild will delete the connectionstrings.config from the obj folder before publish the project as package.

MSBuild missing output files in AfterBuild when solution is cleaned

I'm sure there is something small that I'm missing. Here's the problem:
I have a solution that has multiple projects which after each build will be zipped. Here is an example of the zip creation in one project (they are pretty much identical in others):
<ItemGroup>
<CopySourceFiles Include="$(OutDir)\**\*.*" Exclude="$(OutDir)\**\*.pdb;$(OutDir)\*.mdf;$(OutDir)\*.ldf;$(OutDir)\*.vshost.*" />
</ItemGroup>
...
<Target Name="AfterBuild" Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<MakeDir Directories="$(OutDir)\..\zip_working" />
<!-- first copy the source files specified in the CorySourceFiles ItemGroup above. -->
<Copy SourceFiles="#(CopySourceFiles)" DestinationFiles="#(CopySourceFiles->'$(OutDir)\..\zip_working\%(RecursiveDir)%(Filename)%(Extension)')" />
<!-- Perform the zip by calling the UsingTask. Make sure the DestinationFiles above and the SourceDirectory below are pointing to the same place -->
<Zip SourceDirectory="$(OutDir)\..\zip_working" OutputFilename="$(OutDir)\..\zip\$(ProjectName).zip" />
<!-- Clean up. -->
<RemoveDir Directories="$(OutDir)\..\zip_working" />
</Target>
There is a final project which has links to the zipped files that it combines into a package. All appears normal, but apparently only when the bin and zip_working folders already exist. I.e. if I clean the solution, delete the bin folders and then rebuild, the final zip that is created in the "zip" folder for each project is empty...
And then the zip files have content only after I build again.
So I'm guessing that during the build process, the AfterBuild target is running before the build output files exist. Does that sound right? I trigger the builds purely from within Visual Studio.
Regardless, how can I ensure that I can run a task on build output files only after they've been created?
Applies to Visual Studio 2013 Update 5 / MSBuild 12.0
If you delete everything in OutDir and then build the project, a top-level (as in, not inside a target) ItemGroup is evaluated before the build even starts. Some info can be found here for example. In other words, before a build and with an empty OutDir $(OutDir)\**\*.* evaluates to nothing and your CopySourceFiles item is empty.
The solution is simply to move the ItemGroup inside of the AfterBuild target. It will then be evaluated after the build and hence gets a proper view on the current files in outDir.

MVC3 project build fails because of web.config in obj folder

I have <MvcBuildViews>true</MvcBuildViews> setup in my project files.
Now when I do deployment the first time I get files in obj\release\package\packagetmp. Every subsequent build after this results in a faild build.
Web -> C:\Projects\ProjectX\Web\bin\ProjectX.Web.dll
C:\Projects\ProjectX\Web\obj\release\package\packagetmp\web.config(64):
error ASPCONFIG: It is an error to use a section registered as
allowDefinition='MachineToApplication' beyond application level.
This error can be caused by a virtual directory not being configured as an
application in IIS.
------ Skipped Publish: Project Web, Configuration: Release Any CPU ------
Now if delete the obj folder, I can build fine.
This is rather frustrating to have any build fail after I publish until I manually delete the obj folder. Is there anything I can do to fix this?
Add this to the .csproj file:
<Target Name="AfterBuild" Condition="'$(Configuration)'=='Release'">
<RemoveDir Directories="$(IntermediateOutputPath)" />
</Target>
Seems to delete the files in obj\Release but not the folder itself, at least on my machine.
This problem occurs because MvcBuildViews conflicts with Web Deploy packaging. I got the idea for this solution from http://www.zvolkov.com/clog/2011/02/16/asp-net-razor-lessons-learned/ :
<PropertyGroup>
<PackageDependsOn Condition="'$(DeployOnBuild)'=='true'">
CleanWebsitesPackage;
CleanWebsitesPackageTempDir;
CleanWebsitesTransformParametersFiles;
MvcBuildViews;
$(PackageDependsOn)
</PackageDependsOn>
<BuildDependsOn Condition="'$(DeployOnBuild)'!='true'">
$(BuildDependsOn);
MvcBuildViews
</BuildDependsOn>
</PropertyGroup>
<Target Name="MvcBuildViews" Condition="'$(MvcBuildViews)'=='true'">
<AspNetCompiler VirtualPath="temp" PhysicalPath="$(WebProjectOutputDir)" />
</Target>
Now AspNetCompiler will run before packaging. This works nicely with the msbuild /p:DeployOnBuild=True /p:DeployTarget=Package approach.
This is a known issue with MVC when you enable the build MVC views feature. Hopefully they get it fixed in the next version.
In the mean time, you can run the "Clean Solution" operation to clear out the obj folder instead of doing it manually. The downside is, your entire solution will be rebuilt every time.
Another option that I haven't done, but have considered if my project gets any bigger, is a pre-compile step in the MVC project to remove the web.config from obj\

Resources