Exclude files from web site deployment with msbuild - c#

I have a web site project that I deploy using msbuild. In the project there are some files and folders that are needed for the build (e.g. the web.config part replacement files) but that I don't want to deploy to the target site.
The best I could think of is a post-build target that removes these files, but I'd like to know if there is a way to have these files not copied to the output folder.

Hi Check this blog post out it saved my day,
I was trying to exclude the un-minified version of the javascripts, and use only the minified version when published (I'm removing large javascripts and chirp.config) its only needed for debug.
just put this on the Project file as stated on the link.
<ItemGroup>
<ExcludeFromPackageFolders Include="Scripts\large">
<FromTarget>Project</FromTarget>
</ExcludeFromPackageFolders>
<ExcludeFromPackageFiles Include="Scripts\mash.js.chirp.config" />
<ExcludeFromPackageFiles Include="Content\mash.js.chirp.config" />
</ItemGroup>
The published site will not include the following:
Scripts\large
mash.js.chirp.config

You can select the files and set their "Build Action" to "ExcludeFromPackageFiles". That way visual studio will edit the csproj xml and you don't have to.

in the properties explorer for the files change the option "copy to output directory to "do not copy"

You can use MSDeploy with Web Publishing Pipeline to exclude files to be included in the package creation.
You can use something like this if you want to exclude for example App_Data folder from the deployed package
<Target Name="ExcludeApp_Data" DependsOnTarget="$(ExcludeApp_DataDependsOn)" Condition="$(ExcludeApp_Data)" >
<ItemGroup>
<ExcludeFromPackageFolders Include="App_Data">
<FromTarget>ExcludeApp_Data</FromTarget>
</ExcludeFromPackageFolders>
</ItemGroup>
</Target>
Somehow editor doesn't display the code properly.
The above gets generated inside the proj file when you configure the Package/Publish web. You can add your own target to get it done.
For example, if you want to exclude Scripts\jquery files from your build, create seperate ExcludeScriptFiles.wpp.targets file as below
<ItemGroup>
<ExcludeFromPackageFolders Include="Internal">
<FromTarget>ExcludeScriptFiles.wpp.targets</FromTarget>
</ExcludeFromPackageFolders>
<ExcludeFromPackageFiles Include="Scripts\jquery.js;xyz.js">
<FromTarget>ExcludeScriptFiles.wpp.targets </FromTarget>
</ExcludeFromPackageFiles>
</ItemGroup>
This is just a simple example to write your own target.
Hope this helps

I'm using Visual Studio 2012 with Jenkins and the only thing that worked for me was changing "Build Action" to "None:"
Internally this sets the XML tag in the PROJECT.csproj file from "Content" to "None:"
<None Include="form.coffee" />
I closed the project then manually edited the file using another editor to exclude all my coffee files en mass.
(All my coffee files are still transcompiled to js files.)

Related

After Publish Copy event in VS2019, same functionality as post build event

I'm trying to copy a folder of template files (about 9 thousand files and ~1gb) that are used by my
.net web application to the publish output directory when publishing through VS2019. I have a Post Build script in there to copy them to output when it builds(Works when building locally), but this step seems to get skipped when the files are copied for publishing.
Any ideas how I can add these files so that they get published with rest of application? its a large amount of files so when I tried adding them into VS and change "Copy to output always" VS crashes.
Microsoft has some documentation here about modifying the publish profile to pickup and deploy extra files. Essentially add this to your .pubxml file for the specific publish profile and extra files will be copied.
<Target Name="CustomCollectFiles">
<ItemGroup>
<_CustomFiles Include="..\ExtraFiles\**\*" />
<FilesForPackagingFromProject Include="%(_CustomFiles.Identity)">
<DestinationRelativePath>%(RecursiveDir)%(Filename)%(Extension)</DestinationRelativePath>
</FilesForPackagingFromProject>
</ItemGroup>
</Target>
<PropertyGroup>
<CopyAllFilesToSingleFolderForPackageDependsOn>
CustomCollectFiles;
$(CopyAllFilesToSingleFolderForPackageDependsOn);
</CopyAllFilesToSingleFolderForPackageDependsOn>
<CopyAllFilesToSingleFolderForMsdeployDependsOn>
CustomCollectFiles;
$(CopyAllFilesToSingleFolderForMsdeployDependsOn);
</CopyAllFilesToSingleFolderForMsdeployDependsOn>
</PropertyGroup>
https://learn.microsoft.com/en-us/aspnet/web-forms/overview/deployment/visual-studio-web-deployment/deploying-extra-files

Storing files that available to different projects in solution .NET

I have one solution with 2 .NET MVC projects and some class library projects. Also I have some xml files. I need to put these xml files in one place and have access to them from these 2 .NET MVC projects. These files need also be published.
Can I create App_Data folder in class library project and put these xml files there and use them? Or App_Data folder just related to .NET MVC projects?
How can I resolve my issue?
If your two MVC projects are host on same sever, you can store these xml files anywhere you want.
By adding a appSetting key to store the physical path of these xml files folder into web.config file for these two MVC project.
Then your program just read these files by get the path from the web.config file.
It depends a bit on how you plan to use your xml files, but if I understand you correctly you just want that the file is published to the output directory, that will mean that it will be accessible to any libraries/projects that are running.
So if you put your xml library in a common project that you say you have then you can edit properties of that xml file and set e.g. Build Action to Content or Copy To Output directory to Always (depending on how you do the publish it would probably behave a bit differently).
Then this file should appear in both bin folders.
Alternatively if this does not work, you can create a shortcut to the same file from both projects. You can do this by clicking "add existing item", then click on a triangle next to Add button and in the menu you can chose add as a link
Step 1. Create shared folder (that does not included into your projects) and copy all shared files there.
Step 2. Change .csproj file and describe pre-build action, that just will copy all needed files from shared folder into your project. Something like this:
<Target Name="CodeAnalysisRuleset" BeforeTargets="PreBuildEvent" Condition="$(ConfigurationName) == Debug">
<Exec Command="xcopy /Y "$(SolutionDir)\SharedCodingRules\codeAnalysis.ruleset" "$(ProjectDir)"" />
</Target>
Step 3. Explicitly include new files into your project (again change you .csproj file)
<ItemGroup>
<Content Remove="stylecop.json" />
</ItemGroup>
<ItemGroup>
<AdditionalFiles Include="stylecop.json" />
</ItemGroup>
After those 3 steps you will be able use shared files (configurations, rullsets etc.) in differnt projects.

Visual Studio: How to "Copy to Output Directory" without copying the folder structure?

I have a few dll files in \lib folder of my project folder. In the property page of dll, I have selected "Build Action" as "Content" and "Copy to Output Directory" as "Copy always".
After build I am actually getting the dll copied but they are inside \bin\Release\lib and not in \bin\Release.
Is there a way to copy dll files to \bin\Release (and not to \bin\Release\lib) without writing a post-build script or resorting to nant etc?
instead of <Content> use <ContentWithTargetPath> and specify target path, like this:
<ItemGroup>
<ContentWithTargetPath Include="lib\some_file.dat">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
<TargetPath>some_file.dat</TargetPath>
</ContentWithTargetPath>
<None Include="lib\some_file.dat" />
</ItemGroup>
Note that this entry may not be visible from Visual Studio (2012, 2015, 2017), but once manually added to the csproj, it will appear in Visual Studio. The target path will not be editable through the UI though.
Adding a <None> entry for the file will ensure that it still shows up in Visual Studio's UI.
Keep them in $(ProjectDir)\Lib, but add those files "As a link" to the root of your .csproj. Now they will get copied to bin\Debug (or whatever other output folder) without being in lib.
EDIT: This answer was written way back when ContentWithTargetPath was not available in the versions of VS/MSBuild I was using. Leaving this answer here for people who might have to use an older version of VS. Please stop commenting on this, we all know there are better ways now.
If your main intent is to include DLLs without cluttering up the project root directory, another solution is to move the DLLs to a separate Shared Project and add this as a reference in the original project.
(Note that this post doesn't directly answer this question as it doesn't preserve the folder and project structure, but I found this approach useful because I was able to restructure my project in my case and because I wanted to avoid some of the downsides of the other approaches here.)
Steps
Right-click your Solution -> Add -> New Project -> Shared Project
Add the DLLs to this project (in the root directory of this project, not in a "lib" sub-folder)
(Check DLL file properties are set correctly, e.g. Build Action: Content and Copy to Output Directory: Copy Always)
Right-click the original project's References -> Add Reference -> Shared Projects
Select the shared project you created earlier
The setup looks like this:
If you need to copy files from the Libs directory to the root folder VS2017:
<ItemGroup Condition="'$(Platform)' == 'x64'">
<None Include="Libs\x64\**" Link="\%(Filename)%(Extension)" CopyToOutputDirectory="PreserveNewest" />
</ItemGroup>
<ItemGroup Condition="'$(Platform)' == 'x86'">
<None Include="Libs\x86\**" Link="\%(Filename)%(Extension)" CopyToOutputDirectory="PreserveNewest" />
</ItemGroup>
To any other folder, including Libs(RecursiveDir) folder
<ItemGroup Condition="'$(Platform)' == 'x86'">
<None Include="Libs\x86\**" Link="mycustomfolder\%(RecursiveDir)%(Filename)%(Extension)" CopyToOutputDirectory="PreserveNewest" />
</ItemGroup>
Add the dll-files as a reference to the project, and on the reference set "Copy local" to true.
To add my hat into the ring here, if you want to include a whole directory of content and you don't want to track each individual file in Visual Studio, then you can add this in your project file (for me this is a .vcxproj file of a UWP C++ project):
<ItemGroup>
<Content Include="Content\**">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
</ItemGroup>
Note that the Content directory must be in the same directory as the project file in order to preserve the directory structure.
It seems in VisualStudio 2015 that if the dlls you are 'adding with a link' are in a subfolder of that same project - they will be automatically put a folder, and the output is also placed in a folder like you saw.
If the dlls are in another project or directory on disk not in a subfolder of the project, you can 'Add with a link', and they will be put in the root directory just fine.
The above solutions did not work reliably for me in Visual Studio 2019 Professional v16.8.2. Sometimes the files would copy, sometimes not. After many attempts, it feels like something may have been broken in the latest updates to VS.
This answer shows how to use a post-build script...something the OP asks not to do! So this answer is intended only for those (who like me) were unable to get more traditional methods to work.
Right-click the project and select Add > Existing Item...
Navigate to the lib folder and select the item(s) to add
To the right of Add, click the down arrow and choose Add As Link
Right-click each file in the new "lib" folder in your project, and set "Copy to Output Directory" to "Do not copy"
Open project properties Build Events and add the following Post-build event
,
rem Copy 3rd party DLL(s) to the output directory on successful build
COPY $(ProjectDir)lib\Something.dll $(TargetDir)
COPY $(ProjectDir)lib\SomethingElse.dll $(TargetDir)
Note that you can use wildcards in the post-build event to copy multiple files.
I used this with VS2022:
<ItemGroup>
<ContentWithTargetPath Include="LibFolder\**">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
<TargetPath>%(Filename)%(Extension)</TargetPath>
</ContentWithTargetPath>
</ItemGroup>
Regarding your question, the following steps worked for me in Visual Studio 2019:
In the Visual Studio editor, for your dll, set the "Build Action" setting as "Content" (This might be optional) and "Copy to Output Directory" setting as "Do not copy".
The following will then be generated within the project csproj file:
<ItemGroup>
<Content Include="lib\IncludedDLL.dll" />
</ItemGroup>
Modify the entry to the following instead:
<ItemGroup>
<Content Include="lib\IncludedDLL.dll" />
<Content Include="lib\IncludedDLL.dll">
<Link>IncludedDLL.dll</Link>
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
</ItemGroup>
You can set "CopyToOutputDirectory" option within the project csproj file manually to either "Always" or "PreserveNewest".
In the Visual Studio editor, it will still show the file "Copy to Output Directory" setting as "Do not copy", but the file will be copied to the root output directory upon rebuild.
The above change is not needed if you do not want to copy the file to the root output directory, so if that is the case, you can just manually remove the above change within the project csproj file to revert to the non copying behavior.
An alternate method is just to leave the items as type None. In the solution explorer, click on the ones you want to deploy and set the Content property to True.
Note: I did this in VS2019, and things can change from version to version.
To get this to work, now right-click on your project, and select "Unload Project". Then right-click on the unloaded project and select "Edit project_name.vcxproj".
In the editor, go all the way to the bottom of the file and insert this target right right before the trailing </Project> tag:
<Target Name="CopyContent" AfterTargets="Build">
<Copy SourceFiles="#(None)" Condition="'%(None.DeploymentContent)' == 'true'" DestinationFolder="$(OutputPath)" ContinueOnError="true" />
</Target>
Now right click on the unloaded project and select "Reload Project". Select to save and close if you are prompted.
I also set the OutputDirectory to:
$(SolutionDir)bin\$(Configuration)\$(Platform)\
and the IntermediateDirectory to:
$(SolutionDir)obj\$(Configuration)\$(ProjectName)\$(Platform)\
in the Project Properties General page. This puts the output in a "bin" folder, and the intermediates in an "obj" folder in the root of your solution.
Note: The $(SolutionDir) is not defined when you run MSBuild from the command line. There is a trick you can use to define that to the folder where the .sln file lives using GetDirectoryNameOfFileAbove. (left as an exercise for the reader). Also, it looks like in 2019 they are handling this correctly on the command line anyway. Yeah :) The $(SolutionDir) contains a trailing backslash, hence none after it. The results of each must have a trailing backslash.
Now, if you own Pro or above, please don't do this every time you need to create a project. That would be lame. Instead, once you have your project setup just the way you like it, select Project -> Export Template. You give it a name, and the next time you want to create a project just like that one, just choose that name in the New Project dialog. (In older version, I think this was Files -> Export Teamplate....)
I had the same problem with Visual Studio 2010 / C# Project.
For assemblies (i. e. having the .NET interface) use folder "References" under your project in the Solution Explorer. Right click it, choose "Add existing item" and locate your .dll assembly.
Common .dll files can be placed in a subfolder (as "\lib" was mentioned above) and in the properties select:
Build Action = "HelpFiles"
Copy To OutputDirectory = "If Newer"
This worked for me exactly as desired - during build, the .DLLs are copied to the output directory without the "\lib" subfolder.

Is it possible to copy an entire directory when deploying to Azure?

I'm using Azure and need files to be copied from my project to Azure's approot directory.
For this I go to file-->properties-->build action and set
Build Action: Content
Copy to Output Directory: Copy Always
It works great for files but now I need to upload several directories.
Is it possible to upload an entire directory to Azure's approot?
I'm using .Net 4.5, Visual Studio 2012.
Yes. But as far as I know, you have to edit your .csproj manually to do it. Use a * or ** to recurse, like so:
<ItemGroup>
<None Include="startup\**">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
I usually add a single file manually and then just change the generated line in my .csproj.
In Visual Studio UI folder don't have any property setup instead only files have propertied which is used by compiler and other packaging tools. If selecting each file is an issue, you do can select all the files in specific folder using keyboard shortcut (Shift + _top_file & _bottom_file in folder) and then just use property setup once.

In a .csproj file, what is <None Include="..."> for?

How is
<None Include="C:\foo.bar" />
different from
<Content Include="C:\foo.bar" />
?
The MSDN article on the build action property explains the differences.
None - The file is not included in the project output group and is not compiled in the build process. An example is a text file that contains documentation, such as a Readme file.
Content - The file is not compiled, but is included in the Content output group. For example, this setting is the default value for an .htm or other kind of Web file.
One difference is how they get published; "None" items don't get included in a publish, "Content" items do; for example, on the "Application Files" dialog on the Publish tab.
I am not 100% sure (I read the MSDN description of Build Action property) but just copying that answer from MSDN to StackOverflow does not answer the question completely for me.
The difference of None and Content only has an effect on Web projects. For a command line project, WinForm project or UnitTest project (in my case) etc. None and Content have no different behavior.
MSDN: "project output group" or "Content output group" only terms used in a Web project, right?
In my situation, my MSBuild file had an ItemGroup for image resources that appeared as follows:
<ItemGroup>
<Content Include="Resources\image001.png" />
<Content Include="Resources\image002.png" />
<Content Include="Resources\image003.png" />
<Content Include="Resources\image004.png" />
<None Include="Resources\image005.png" />
<None Include="Resources\image006.png" />
<None Include="Resources\image007.png" />
</ItemGroup>
While my project was building fine, this left me wondering why I had a mix of Content and None item type elements in my ItemGroup. This MSDN article (for Visual Studio 2010) gave me the guidance I was looking for:
Note that when the resource editor adds an image, it sets Build
Action to None, because the .resx file references the image
file. At build time, the image is pulled into the .resources file
created out of the .resx file. The image can then easily be accessed
by way of the strongly-typed class auto-generated for the .resx file.
Therefore, you should not change this setting to Embedded
Resource, because doing this would include the image two times in
the assembly.
Resolution: With this guidance, using a text editor, I changed the Content item type elements to None.
Also, for an overview of MSBuild items, see this MSDN article.
Content files are not included in a build, but are included in a publish.
None files are not included in a build or publish, unless they are configured that way by you. For instance, a "Copy to Output Directory" setting of "Always" or "Newer", will cause them to be included in both a build and publish.
I have a project that contains no compilable items (it stores html and javascript for jasmine unit tests).
One day my solution (that contained said project) stopped compiling saying "The target "Build" does not exist in the project".
I added an import to bring in the compiler, which worked fine on my machine but failed using msbuild on the build server.
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
I then changed a line from
<None Include="SpecRunner.html" />
to
<Content Include="SpecRunner.html" />
and it worked on the build server as well.
You need None in a template project file to include files you define in the .vstemplate otherwise they are lost in the creation & translation process. They get left behind in the temp folder it uses to build everything and then deleted shortly after.
In my case .Pubxml is one of those files among None list. It's not meant for solution building or as a static file for web project. But to publish the site to Azure, the configurations are present in this.
As per Microsoft article these are the major types we see among .csproj file tags:
None - The file is not included in the project output group and is not
compiled in the build process. An example is a text file that contains
documentation, such as a Readme file.
Compile - The file is compiled into the build output. This setting is
used for code files.
Content - The file is not compiled, but is included in the Content
output group. For example, this setting is the default value for an
.htm or other kind of Web file.
Embedded Resource - This file is embedded in the main project build
output as a DLL or executable. It is typically used for resource
files.

Categories

Resources