Exclude file from project via msbuild - c#

In my .csproj file, I am creating directories containing files, and these directories are being created in the main project directory as intended. For certain reasons, I cannot generate these directories in bin\debug. However, I do not want the files generated in the directories to be included in the project, as I do not want them to be checked in.
How can I exclude the files from my project automatically through msbuild?
For reference, I have tried the following, and though the files get generated as expected, they are still being added to the project unintentionally:
<Target Name="BuildThings" AfterTargets="Build" BeforeTargets="GatherStagingFiles" Inputs="#(Compile)" Outputs="$(GeneratedFilesDirectory)">
<Exec WorkingDirectory="$(MSBuildProjectDirectory)" Command="$(ToolPath) buildpackage -InputDir:$(MSBuildProjectDirectory)\$(OutDir) -OutputDir:$(MSBuildProjectDirectory)\$(GeneratedFilesDirectory)" />
</Target>
<Target Name="HideFiles" DependsOnTargets="BuildThings">
<ItemGroup>
<GeneratedFiles Include="$(MSBuildProjectDirectory)\$(GeneratedFilesDirectory)\file.txt">
<InProject>false</InProject>
</GeneratedFiles>
</ItemGroup>
</Target>

Related

Including a Folder in NuGet Package and have it install into project as file .netcore/Razor

I am using Visual Studio 2019 and creating NuGet packages successfully with this method:
https://learn.microsoft.com/en-us/nuget/quickstart/create-and-publish-a-package-using-visual-studio?tabs=netcore-cli
All going well, but there are some settings (.json) files contained within a directory PageSettings/
When I publish my NuGet package and then install it into a new project, this directory appears in VS as a linked item (see pic). So as a user I can access the files, but they don't "exist" when the project is run.
This means if I run this project without physically copying and adding these files I get ArgumentException: The directory name 'Path-To-project\pagesettings' does not exist. (Parameter 'Path')
I can see why this is happening, but can't work out how to change it, or if it is possible.
The article linked above suggests adding code to the csproj file like:
<ItemGroup>
<Content Include="readme.txt">
<Pack>true</Pack>
<PackagePath>\</PackagePath>
</Content>
</ItemGroup>
But that doesn't work and in fact seems unnecessary since the Pack command is including my files, just not creating them properly when installing.
Also - it would be extremely handy if there was a way to tell VS to prompt whether to install this file or not. Since it is settings, if a user changes the settings and then later installs an updated version of my NuGet package I would not want it to overwrite their customised settings... perhaps this is why the link design happens... if so, if someone could confirm?
Actually, you should create a .props file in your nuget package.
1) create a file called <package_id>.props file in your nuget project.
Like this:
Note: if your created nuget package called test.1.0.0.nupkg, the file should be named as test.props so that it will work.
2) add these in the test.props file:
<Project>
<Target Name="CopyFiles" BeforeTargets="Build">
<ItemGroup>
<File Include="$(MSBuildThisFileDirectory)..\Pagesettings\*.*"></File>
</ItemGroup>
<Copy SourceFiles="#(File)" DestinationFolder="$(ProjectDir)Pagesettings"></Copy>
</Target>
</Project>
3) add these in xxx.csproj file:
<ItemGroup>
<None Include="Pagesettings\*.*(the json files' path of your nuget project)" Pack="true" PackagePath="Pagesettings">
</None>
<None Include="build\*.*" Pack="true" PackagePath="build"></None>
</ItemGroup>
then reapck your project.
4) then clean your nuget caches or delete all files under C:\Users\xxx(current user)\.nuget\packages.
5) when you insall this new version of the nuget package, please build your main project again to run the target to generate the files.
Besides, there is also a similar issue about this.

asp.net deploy 3rd party dlls to bin folder

BACKGROUND
I have created an ASP.NET webforms (4.6) website that has some 3rd party components in it. In order for this to work I have created a SharedResources folder that contains the DLLs needed. I've added a reference and those DLLs get copied to the BIN when publishing - GREAT. BUT there are some other DLLs needed that cannot be referenced as they are not valid assemblies or COM components.
MY PROBLEM
How can I add to the build, dll's that are in a folder (SharedResources\3rdParty) so that when I click 'Publish' it dumps all those dll's into the bin folder of the website.
WORKAROUND
(trying to avoid this)
I have set the dll Build action to "Content - always copy" and this gives me a folder of DLLs in ~\SharedResources\3rdParty\ and then the application complains of missing dll's so I copy them to the bin manually - that can't be right!
Thanks
Right click your project go to properties and, in the build events tab paste this into your Pre-build event command line: copy $(ProjectDir)SharedResources\3rdParty*.dll $(ProjectDir)$(OutDir)
This will not work when you publish the website. You will have to create your own targets in the project file or a separate targets file and call as follows -
Add following -
<ItemGroup>
<ThirdPartyDllDependencies Include="$(SolutionDir)..\..\Lib\ThirdPartyDll\*.dll" SkipUnchangedFiles="true" />
</ItemGroup>
<Target Name="PublishThirdPartyDllDependencies">
<Copy SourceFiles="#(ThirdPartyDllDependencies)" DestinationFolder="$(OutDir)\" />
<Copy SourceFiles="#(ThirdPartyDllDependencies)" DestinationFolder="$(WebProjectOutputDir)\bin\" />
</Target>
<!-- This target is responsible for adding the ThirdPartyDll and dependencies to the bin directory while Publishing the website. -->
<Target Name="CustomCollectFiles">
<ItemGroup>
<_CustomFiles Include="$(SolutionDir)..\..\Lib\ThirdPartyDll\ThirdPartyDll11\64Bit\*.dll" />
<FilesForPackagingFromProject Include="%(_CustomFiles.Identity)">
<DestinationRelativePath>$(WebProjectOutputDir)\bin\%(RecursiveDir)%(Filename)%(Extension)</DestinationRelativePath>
<DestinationRelativePath>$(OutDir)\%(RecursiveDir)%(Filename)%(Extension)</DestinationRelativePath>
</FilesForPackagingFromProject>
</ItemGroup>
</Target>
<PropertyGroup>
<CopyAllFilesToSingleFolderForPackageDependsOn>
CustomCollectFiles;
$(CopyAllFilesToSingleFolderForPackageDependsOn);
</CopyAllFilesToSingleFolderForPackageDependsOn>
</PropertyGroup>

Create folder while publishing with MSBuild

I am Trying to create a Temp folder while doing the publish of my Web Application Project with file system location in Visual Studio 2015.I have tried adding the code below in .csfile but its not Creating folder in the target location of the Publish Directory.If given Static location to create folder its working fine.How can get Publish Directory dynamically?
<Target Name="CustomCollectFiles" AfterTargets="Build">
<MakeDir Directories="$(PublishDirectory)$(OutputDirectoryTemp)" />
</Target>
<PropertyGroup>
<OutputDirectoryTemp>\Temp\</OutputDirectoryTemp>
</PropertyGroup>
Create folder while publishing with MSBuild
You need to declare attributes PublishDirectory by creating an element with the attribute name as a child of the PropertyGroup element, because there is no such MSBuild Macros for this, you can check the Common Macros for Build Commands and Properties.
As test, I set PublishDirectory to the path D:\Publish:
<PropertyGroup>
<PublishDirectory>D:\Publish</PublishDirectory>
</PropertyGroup>
Then I add a output command line <Message Test="xxx" /> in the target to output the content of $(PublishDirectory)$(OutputDirectoryTemp):
<Target Name="CustomCollectFiles" AfterTargets="Build">
<MakeDir Directories="$(PublishDirectory)$(OutputDirectoryTemp)" />
<Message Text="$(PublishDirectory)$(OutputDirectoryTemp)">
</Message>
</Target>
<PropertyGroup>
<OutputDirectoryTemp>\Temp\</OutputDirectoryTemp>
</PropertyGroup>
<PropertyGroup>
<PublishDirectory>D:\Publish</PublishDirectory>
</PropertyGroup>
In the output window, you will see following log:
And the folder Temp would be created:
If you have already defined the variable of PublishDirectory, you can try to use the output command line <Message Test="xxx" /> check if the path is correct.
Update:
I will like to get the target location of the Publish Directory dynamically not static or hard coded
Since you want to get the target location of the Publish Directory dynamically, as we know, the location of the Publish Directory was stored in the .pubxml file, in the node <publishUrl>D:\Publish\Test</publishUrl>, to get this value dynamically, we could use $(publishUrl) to get this value in the target, However, the publishing process is after the build, we could not get this value in the build process, so we need to change the order of this target from AfterTargets="Build" to AfterTargets="PipelineTransformPhase". The target should be:
<Target Name="CustomCollectFiles" AfterTargets="PipelineTransformPhase">
<MakeDir Directories="$(publishUrl)$(OutputDirectoryTemp)" />
<Message Text="$(publishUrl)$(OutputDirectoryTemp)" />
</Target>
<PropertyGroup>
<OutputDirectoryTemp>\Temp\</OutputDirectoryTemp>
</PropertyGroup>
In this case, when you publish your project to the system location, the publish directory will be stored in the publishUrl, we could get it in that target.
Hope this helps.
A little irrelevant at this point in time, but I think it may help someone like me. Whenever I searched how to dynamically add the folders and files within the same project in my publish profile in Azure DevOps, I landed on this question. So, I decided to put my answer here if it can help someone.
MSBuild expects you to make sure that you include certain files into the project file if you want Azure to deploy them during a git deployment. It is very frustrating, especially when you're using an external tool to copy files into a certain folder.
Wouldn’t it be nice if Visual Studio and (therefore) MSBuild just recursively included and deployed a folder of files within the same project without you having to define it in the publish profile?
You have to hand-edit the .csproj/.vbproj file (using Notepad++), but all you need to do is use a wildcard in the Include statement:
MyProject.Web.vbproj
<!-- double wildcards include all files and folders -->
<Content Include="folder\**" />
<!-- You can also filter certain type of files (e.g. .js files) -->
<Content Include="folder\*.min.js" />
It helped me tremendously.
Try specifying your PropertyGroup before your target, to ensure it has been created.
Also check the value of PublishDirectory to make sure it is a valid path - I suspect it may come with a "\" on the end of it, so you're ending up with two slashes

Visual Studio/MSBuild copy referenced class library's app.config as *.dll.config to bin folder of current project

I have a class library that is referenced by many other web application projects. It has many settings in its app.config that I wish to use in all of the referencing web projects. When the class library is built, it copies the app.config to its own bin folder as <assembly.name>.dll.config.
How do I ensure that <assembly.name>.dll.config is copied to the bin folder of each of my referencing web application projects?
Visual Studio / MSBuild does not seem to do this by default.
Changing Copy to Output Directory or Build Action (in any combination) does not work.
SlowCheetah VS extension appears to do what I want as an unintended side-effect of its config transform process, but I want to do this without any 3rd-party extensions.
As an aside: It's impractical to manually put all of this config in each of the web application projects. I can read the file by looking for <assembly.name>.dll.config in the bin folder, and extract the settings from there. I can already do this, so that's not an issue - I just need to ensure the file is going to be there for reading
This can be achieved without 3rd-party tools by adding the following to the class library's project file, assembly.name.csproj:
// Find this <Import> element for Microsoft.CSharp.targets
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
// Add this <ItemGroup> element immediately after
<ItemGroup>
<Content Include="app.config">
<Link>$(TargetName).dll.config</Link>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
</ItemGroup>
This causes the app.config to be copied to whichever project is referencing it as <assembly.name>.dll.config. It's good because you only need to configure the one .csproj file and the effect cascades out to all referencing projects.
Visual Studio 2015 and earlier
For Visual Studio 2015, I am using the solution of #theyetiman (see this answer):
<ItemGroup>
<None Include="app.config" />
</ItemGroup>
<ItemGroup>
<None Include="app.config">
<Link>$(TargetFileName).config</Link>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
</ItemGroup>
(The import of Microsoft.CSharp.targets was already present.)
Visual Studio 2017
During my experiments, Visual Studio 2017 seems to handle configuration files as expected out of the box. No manual modification of the project file is needed.

How do i have a .csproj build a .proj file before building itself?

I have a .csproj file and a .proj file. As part of my .proj file I am generating a file to include in the .csproj, so the .proj needs to run first.
How can this be done. I originally tried to add a project reference as follows:
<ProjectReference Include="..\FileGenerator\FileGenerator.proj">
<ReferenceOutputAssembly>false</ReferenceOutputAssembly>
</ProjectReference>
This however gives me the error:
error MSB4057: The target "GetNativeManifest" does not exist in the project
I then noticed there is a BeforeBuild target in my csproj file.
Can I use this to have the other file be built?
Use MSBuild task to invoke other projects. Example:
<Target Name="BeforeBuild">
<MSBuild Projects="..\FileGenerator\FileGenerator.proj" Targets="Build" />
</Target>
If you need any cleanup done as part of the common Clean target, you can plug in custom cleanup target like this:
<Target Name="FileGeneratorClean" BeforeTargets="Clean">
<MSBuild Projects="..\FileGenerator\FileGenerator.proj" Targets="Clean" />
</Target>

Categories