How to set Visual Studio to Publish pdf files automatically - visual-studio

Is there a way to set visual studio to publish all pdf files?
I know that you can set each individual pdf file in a project with the Build Action
"Content" property.
But that means doing the same thing 100's of times for my current project, is there a way to change a global setting to do the same thing?

there is an easier way, you have to make sure your file is included in the project first, then right-click on the file go to properties, there will be an option "copy to output directory", choose "copy always"
Good luck

Just right click on the file you want to include, choose properties, in the properties window change build action to content. This will include the file during publish.

Add a post build event with the following command:
xcopy "$(ProjectDir)myPdfs\*.pdf" "$(TargetDir)myPdfs\" /S /Y
Note in the above command myPdfs is just a subfolder of your project directory that contains all the PDF files. If you have more than one of these subfolders you need to run the command for each.
Hope this works!!

Suppose you had the PDFs you wish to deploy outside the project in c:\PDFs, modify the .csproj
<ItemGroup>
<Content Include="c:\PDFs\**\*.pdf" />
</ItemGroup>
If they're in a folder "MyPdfs" relative to the root of the project
<ItemGroup>
<Content Include="MyPdfs\**\*.pdf" />
</ItemGroup>
Some further details about this can be found on: https://stackoverflow.com/a/12202917/37055

Open the csproj file and change :
<None Include="my.pdf">
to:
<Content Include="my.pdf">

You could edit your project file directly to add the required <CopyToOutputDirectory>Always</CopyToOutputDirectory> elements to the PDF files. (If your project isn't under source control, test on a copy first and keep backups in case it all goes wrong)

CopyToOutputDirectory will copy the files to the bin folder when you publish. Setting "Build Action" to "Content" will copy the files without the need of CopyToOutputDirectory setting. But this is still needs to be done on each file. You could make a regex replace in project file from <None Include="XXX.pdf" /> to <Content Include="XXX.pdf" />.

Related

How do I add files to VS Solution Explorer with a wildcard in the project file?

In my project file I include all of the .cpp and .h files in a directory by using a wildcard as shown in the code snippet below. Everything compiles just fine.
The annoying issue I run into is I have to add files to the Solution Explorer manually via the Add Existing Item dialog. If I don't use a wildcard and spell out every file, I don't have the same problem. Not something I want to do with a boatload of source files though.
Is there a way to get these wildcard includes into the Solution Explorer?
<ItemGroup>
<ClCompile Include="$(SrcDir)\*.cpp" >
<Link>%(FileName)</Link>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="$(SrcDir)\*.h">
<Link>%(RecursiveDir)\%(FileName)</Link>
</ClInclude>
</ItemGroup>

Visual studio 2017 Excludefoldersfromdeployment but include some subfolder

I was wondering if it's possible to include some sub-folder on publication, of an excluded folder.
Let's assume i have this structure:
/Folder1/
/Folder1/FileX
/Folder1/FileY
/Folder1/SubFolder1/
/Folder1/SubFolder2/
What i want is to exclude the whole Folder1 content, but include only a specific set of sub-folder (in my example SubFolder1).
The Folder1 folder is excluded with the ExcludeFoldersFromDeployment in the .pubxml:
<ExcludeFoldersFromDeployment>Folder1</ExcludeFoldersFromDeployment>
You haven't told us what this .pubxml file is, so there is a limit to what we can help you with.
But in general:
The construct that deals with files and folders in MSBuild is Items.
You want an Item here, not an MSBuild property.
So you could easily use an item to point to a specific sub folder in your build environment like this:
<ItemGroup>
<!-- This will grab all files in SubFolder1 but not recursively -->
<DeployThese Include="/Folder1/SubFolder1/*.*" />
</ItemGroup>
You can then do anything you want with that Item. You could copy the files in it somewhere else, or anything else with them.
The files are accessed later by using #(DeployThese)
I was wondering if it's possible to include some sub-folder on
publication, of an excluded folder.
Yes, it’s possible.
Note: One point we should know, as you’ve used “ExcludeFoldersFromDeployment” element in .pubxml to exclude the entire Folder1 directory. Some deploy actions in .xxproj file may be overwritten or affected by it.
So, to achieve your goal we have to follow two steps:
1. Copy the SubFolder to a new folder (A new folder in $(ProjectDir) can be better)
2. Add the content of SubFolder to publish, and choose the structure you want
Here’s a workaround:
1: Add a PreBuildEvent prorerty in .csproj file.
<PropertyGroup>
<PreBuildEvent>xcopy "$(ProjectDir)/Folder1/SubFolder1" "$(ProjectDir)/NewFolder" /E /Y /I</PreBuildEvent>
</PropertyGroup>
2: Add following markup to .csproj file, it helps publish extra files to publish folder in Asp.net:
<PropertyGroup>
<PipelineCollectFilesPhaseDependsOn>
CustomCollectFiles;
$(PipelineCollectFilesPhaseDependsOn);
</PipelineCollectFilesPhaseDependsOn>
</PropertyGroup>
<Target Name="CustomCollectFiles">
<ItemGroup>
<_CustomFiles Include="NewFolder\**\*" />
<FilesForPackagingFromProject Include="%(_CustomFiles.Identity)">
<DestinationRelativePath>MyStructureUnderPublishFolder\%(RecursiveDir)%(Filename)%(Extension)</DestinationRelativePath>
</FilesForPackagingFromProject>
</ItemGroup>
</Target>
For this markup, we only need to change two paths to meet our needs.
First:The CustomFiles refers to the folder whose content will be published.
Second:The MyStructureUnderPublishFolder refers to the structure you want under publish folder. If you want a Folder1 which only has a SubFolder in it after deployment, change it to Folder1/SubFolder1, or change it to SubFolder1 if you want a simple Subfolder1 under Publish folder.
More information about adding extra files to publish see here.

Copy entire directory to output folder maintaining the folder structure?

I want a specific directory to be copied to output folder ("bin") on every build. I think it can be handled via post build scripts. But I'm not sure how to copy a directory itself. I know how to handle specific files.
For eg, this works for a file:
In
Project > Properties > Build Events> Post Build
COPY "$(SolutionDir)Resources\Release Notes.pdf" "$(TargetDir)"
But suppose I have a directory Template, now I need everything under Template to come to bin folder upon successful build maintaining the folder structure.
I tried this:
COPY "$(SolutionDir)Resources\Template\" "$(TargetDir)"
Only the files in Template directory gets copied this way and not the sub directories and the files inside Template folder. I want the folder Template itself to come inside my output bin folder. In other words, bin should look like:
bin > Template > abc.xxx
xxx.yyy
Subdirectory1 > asd.qwe
zxc.qwe
Subdirectory2 > ...
This could be a duplicate, but I couldn't find a relevant thread. Thanks.
I just added this to my *.csproj file (right click Edit Project File)
<ItemGroup>
<Content Include="MYCUSTOMFOLDER\**">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
</ItemGroup>
I think for this the directory needs to be on same hierarchy level as *.csproj file or bellow that.
This worked for me. /S is the key which copies everything recursively.
XCOPY "$(SolutionDir)Resources\Template" "$(TargetDir)\Template\" /S
Since I wanted files to be overwritten every time without a prompt, I added a /Y switch as well.
XCOPY "$(SolutionDir)Resources\Template" "$(TargetDir)\Template\" /S /Y
Try XCOPY instead of COPY; e.g.
XCOPY "$(SolutionDir)Resources\Template\" "$(TargetDir)\Template" /s /i /y
More info on XCOPY here...
http://www.computerhope.com/xcopyhlp.htm
Here's an additional solution working on Visual Studio 2019 as of the date of this post. This will copy the folder structure recursively and all files within. Tested on a C++ .vcxproj in a multi-project solution.
First, start by editing your [ .proj / .vcxproj / .csproj ] file. Once open, find your project scoped tag. If you already have ItemGroups within, then paste the code below directly after the existing ones. Otherwise, add it in before the PropertyGroup tags. Then modify the Include & Link parameters for the folder structure you wish to copy to the output path.
<ItemGroup>
<Content Include="..\Assets\**\*.*">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
<DeploymentContent>true</DeploymentContent>
<Link>Assets\%(RecursiveDir)\%(Filename)%(Extension)</Link>
</Content>
</ItemGroup>
Note: If you have multiple top level folders, like JS, IMG, BIN, etc., then create a new entry for each one.
The solution by CodingYourLife almost worked for me, but I found out that PreserveNewest was not being respected. I found a solution on the Visual Studio forums that works correctly. My .CSPROJ now looks like this:
<Content Include="assets\**">
<Link>assets\%(RecursiveDir)\%(Filename)%(Extension)</Link>
<TargetPath>assets\%(RecursiveDir)\%(Filename)%(Extension)</TargetPath>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
Note: This solution requires Visual Studio 16.10 or newer.
I have a working solution of this question:
<Target Name="PostBuild" AfterTargets="PostBuildEvent">
<ItemGroup>
<CommonFont Include="..\common\src\Web\wwwroot\css\fonts\*.*" />
</ItemGroup>
<Copy SourceFiles="#(CommonFont)" DestinationFolder="wwwroot\css\fonts" SkipUnchangedFiles="true" />
</Target>
This is the only solution that worked for me (VS2022, .Net Framework):
<ItemGroup>
<ContentWithTargetPath Include="..\..\..\Libraries\Core\Business\Vodovoz.Reports\Reports\**">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
<TargetPath>Reports\%(RecursiveDir)\%(Filename)%(Extension)</TargetPath>
</ContentWithTargetPath>
</ItemGroup>

Run MSBuild script once for solution

I have got a solution with 30 projects. All these projects have the same custom MSBuild script which copies all the compiled files (from the _PackageTempDir) to another location on the hard drive.
<ItemGroup>
<DeployFilesBin Include="$(_PackageTempDir)\bin\*.*" />
</ItemGroup>
<Copy SourceFiles="#(DeployFilesBin)" DestinationFiles="#(DeployFilesBin->'$(DeployDestinationBin)\%(RecursiveDir)%(Filename)%(Extension)')" SkipUnchangedFiles="True" />
When I change the name of a file, this file will not be removed from the destination directory which is unwanted because I could get an ambiguous reference exception.
I do not want a global MSBuild script because I would like to use Visual Studio's build shortcut for executing csproj files.
Is there any way to delete all files in the destination directory and then execute all csproj files? Maybe a target which is fired once of a way to declare a global variable to check if that specific cleanup target has already ran?

How to make Visual Studio copy a DLL file to the output directory?

I have a Visual Studio C++ project that relies on an external DLL file. How can I make Visual Studio copy this DLL file automatically into the output directory (debug/release) when I build the project?
Use a post-build action in your project, and add the commands to copy the offending DLL. The post-build action are written as a batch script.
The output directory can be referenced as $(OutDir). The project directory is available as $(ProjDir). Try to use relative pathes where applicable, so that you can copy or move your project folder without breaking the post-build action.
$(OutDir) turned out to be a relative path in VS2013, so I had to combine it with $(ProjectDir) to achieve the desired effect:
xcopy /y /d "$(ProjectDir)External\*.dll" "$(ProjectDir)$(OutDir)"
BTW, you can easily debug the scripts by adding 'echo ' at the beginning and observe the expanded text in the build output window.
The details in the comments section above did not work for me (VS 2013) when trying to copy the output dll from one C++ project to the release and debug folder of another C# project within the same solution.
I had to add the following post build-action (right click on the project that has a .dll output) then properties -> configuration properties -> build events -> post-build event -> command line
now I added these two lines to copy the output dll into the two folders:
xcopy /y $(TargetPath) $(SolutionDir)aeiscontroller\bin\Release
xcopy /y $(TargetPath) $(SolutionDir)aeiscontroller\bin\Debug
To do it with the GUI, first add the file(s) to the project: right-click the project, select "Add...", then "Existing Item", then browse to the file or files you want to add and click "Add". Next, tell Visual Studio to copy the file when you build: right-click the file you want to copy, select "Properties". You'll see a list of properties, including "Item Type". Change the "Item Type" to "Copy File". Hit OK and you're done.
Here's the file properties dialog:
Looking in the *.vcxproj file, the steps above add something like this:
<ItemGroup>
<CopyFileToFolders Include="libs\a.dll" />
<CopyFileToFolders Include="libs\a.dll" />
</ItemGroup>
I couldn't find any official documentation for <CopyFileToFolders>, but clearly it's supported or the GUI wouldn't use it. But, if you're doing it by hand and an undocumented item type makes you uncomfortable you can always use the well known but slightly more verbose <Content> type:
<ItemGroup>
<Content Include="libs\a.dll" >
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="libs\b.dll" >
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
</ItemGroup>
Add builtin COPY in project.csproj file:
<Project>
...
<Target Name="AfterBuild">
<Copy SourceFiles="$(ProjectDir)..\..\Lib\*.dll" DestinationFolder="$(OutDir)Debug\bin" SkipUnchangedFiles="false" />
<Copy SourceFiles="$(ProjectDir)..\..\Lib\*.dll" DestinationFolder="$(OutDir)Release\bin" SkipUnchangedFiles="false" />
</Target>
</Project>
(This answer only applies to C# not C++, sorry I misread the original question)
I've got through DLL hell like this before. My final solution was to store the unmanaged DLLs in the managed DLL as binary resources, and extract them to a temporary folder when the program launches and delete them when it gets disposed.
This should be part of the .NET or pinvoke infrastructure, since it is so useful.... It makes your managed DLL easy to manage, both using Xcopy or as a Project reference in a bigger Visual Studio solution. Once you do this, you don't have to worry about post-build events.
UPDATE:
I posted code here in another answer https://stackoverflow.com/a/11038376/364818
xcopy /y /d "$(ProjectDir)External\*.dll" "$(TargetDir)"
You can also refer to a relative path, the next example will find the DLL in a folder located one level above the project folder. If you have multiple projects that use the DLL in a single solution, this places the source of the DLL in a common area reachable when you set any of them as the Startup Project.
xcopy /y /d "$(ProjectDir)..\External\*.dll" "$(TargetDir)"
The /y option copies without confirmation.
The /d option checks to see if a file exists in the target and if it does only copies if the source has a newer timestamp than the target.
I found that in at least newer versions of Visual Studio, such as VS2109, $(ProjDir) is undefined and had to use $(ProjectDir) instead.
Leaving out a target folder in xcopy should default to the output directory. That is important to understand reason $(OutDir) alone is not helpful.
$(OutDir), at least in recent versions of Visual Studio, is defined as a relative path to the output folder, such as bin/x86/Debug. Using it alone as the target will create a new set of folders starting from the project output folder. Ex: … bin/x86/Debug/bin/x86/Debug.
Combining it with the project folder should get you to the proper place. Ex: $(ProjectDir)$(OutDir).
However $(TargetDir) will provide the output directory in one step.
Microsoft's list of MSBuild macros for current and previous versions of Visual Studio
I had a similar question. In my project, there were couple of external DLLs. So I created a new folder in the project called "lib" and copied all the external dlls to this folder.
Add a reference to these DLLs.
Go to Project References>dll properties and change the following properties
enter image description here

Resources