How to publish additional files into bin folder - c#

My .net web app project also includes some unmanaged dlls as additional files.
These are a couple of levels deep in subfolders.
When I publish this project I need these files to be copied to the bin folder alongside all the other binaries.
No matter what settings I try, the best I can get is for them to be published into their existing folder structure which is not where I need them to be.
I've created a PostBuild event to copy the files and this works when building locally but not when publishing to a server. I've not been able to get PostPublish events to work in the same way.
Is there another way to achieve this?
Note this is similar but not the same as a previous question:
Publish unmanaged DLL from referenced project

I have a similar setup. 2 projects in my solution, one .NET Core and the other C++. When I am going to publish the dotnetcoreapp2.2 I want to include the precompiled C++ DLL from the other project.
#JuanR's answer is not working for me, though it is already pretty close to my version. It looks like the <ItemGroup> needs to be in the <Target> tag.
<Target Name="PrepublishScript" BeforeTargets="PrepareForPublish">
<ItemGroup>
<DataModelFiles Include="$(ProjectDir)..\MyCppProject\bin\Release\MyCppProject.dll" />
</ItemGroup>
<Copy SourceFiles="#(DataModelFiles)" DestinationFolder="$(PublishDir)" SkipUnchangedFiles="false" />
</Target>

Try using an after-publish task.
You can create an item group for copy:
<ItemGroup>
<binFilesToCopy Include="$(OutDir)\somepath\to\yourexternalDLLFolder\*" />
<!-- Add more folders/files you want to copy here -->
</ItemGroup>
Then add a target for after publishing:
<Target Name="AfterPublish">
<Copy SourceFiles ="#(binFilesToCopy)" DestinationFolder ="$(OutDir)\bin" />
</Target>
I did this mostly from memory so double-check for syntax, but get you the idea.

In the properties of the file you can set Copy to output directoryto Copy always or you can edit the solution file, expand the xml tag of the file needed and add <CopyToOutputDirectory>Always</CopyToOutputDirectory> as sub-tag.

Related

.NET 6 obfuscation

I'm trying to obfuscate an .exe file obtained after compiling my .NET 6 project with the "Produce a single file" option, the problem is that no obfuscator works on it, I wanted to know if anyone knows why?
Thanks in advance for your answer
You have to obfuscate main application dll, which is located in the "obj\Release\net6.0-windows\win-x64" folder and copy obfuscated dll to the path.
Here is a working example using Obfuscar. These lines are located in the .csproj file.
<Target Name="Obfuscation" AfterTargets="AfterCompile" Condition="'$(PublishProtocol)'!=''">
<Exec Command=""$(Obfuscar)" obfuscar.xml" />
</Target>
<Target Name="PostBuild" AfterTargets="PostBuildEvent" Condition="'$(PublishProtocol)'!=''">
<Exec Command="COPY "C:\Users\Application\obj\Release\net6.0-windows\win-x64\Obfuscated\Application.dll" "C:\Users\Application\obj\Release\net6.0-windows\win-x64\Application.dll"" />
</Target>
After that, when you publish single file exe, your application code inside the archive will be obfuscated.
When you publish a .NET application as a single file, the actual code is located in the DLL file. The EXE file is just a launcher.
Returning to the obfuscation, the idea is to obfuscate the assembly right after it is placed to the intermediate directory by a compiler. E.g. if you use ArmDot you just write:
<Target Name="Protect" AfterTargets="AfterCompile" BeforeTargets="BeforePublish">
<ItemGroup>
<Assemblies Include="$(ProjectDir)$(IntermediateOutputPath)$(TargetFileName)" />
</ItemGroup>
<ArmDot.Engine.MSBuildTasks.ObfuscateTask
Inputs="#(Assemblies)"
ReferencePaths="#(_ResolveAssemblyReferenceResolvedFiles->'%(RootDir)%(Directory)')"
SkipAlreadyObfuscatedAssemblies="true"
/>
</Target>
The same approach can be used with any obfuscator. The key thing is to use the following path: $(ProjectDir)$(IntermediateOutputPath)$(TargetFileName).
After that, the obfuscated assembly (DLL) is published.

Including auto-generated static content in Visual Studio

My web application has a node process that runs things like transpilation and minification, and produces a bunch of output files. We've had problems with our CI server not sending these auto-generated files out unless they were manually included in the project.
Manually including auto-generated files is a pain, is easy to forget, and just an all-around bad idea.
How can I get visual studio to just include everything under a specific folder, no matter what. I just need these files to exist to my script loader can load them when needed.
Per this answer I tried
<Target Name="BeforeBuild">
<ItemGroup>
<Content Include="2\application-base\**\*.js" />
</ItemGroup>
</Target>
to no avail. After adding that I've tried building the solution, the project, re-building the project, none of which cause anything in that folder to show up in the solution explorer as included.
Just put Content in the main ItemGroup of the project.
Ie
<ItemGroup>
<Content Include="2\application-base\**\*" />

Add a directory to clickonce

I want to add a directory and its files to visual studio keeping the root dir. I did this with the below piece of XML on my .csproj file but this does add all its files to solution explorer but exclude the root. The file are variable and I don't want to hard code them add manually. That's why I'm looking for an automated solution.
How do I fix this?
<ItemGroup>
<Content Include="bin\x86\release\myFolder\**\*">
<Visible>true</Visible>
<Link>%(RecursiveDir)%(Filename)%(Extension)</Link>
</Content>
I would like to include this directory (and not only its files) in ClickOnce publishing.
I couldn't think of any automatic way to created the folder and make the solutin explorer aware of this files. So I created the folder on right click on project -> add folder. Unloaded the project and edited the piece of XML which add the directory I've created to solution explorer to this:
<ItemGroup>
<Content Include="foo\*.*">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
<Visible>True</Visible>
</Content>
</ItemGroup>
Now solution explorer is aware of that files and so does clickonce. The files get properly in the app.publish folder
NOTE: On this project, the foo files came from another folder (external C++'s binary output folder). They're copyed at post-build time. The folder name is sort of hard-coded (I need to chage them manually on the VS solution explorer, on the .csproj file and in the xcopy command-line on post-build) cause I didn't find any other way to do that.
<Target Name="AddGeneratedFiles" AfterTargets="SOMETASK">
<CreateItem Include="*.cpp">
<Output TaskParameter="Include" ItemName="ClCompile" />
</CreateItem>
</Target>

Exclude files from web site deployment with msbuild

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.)

Out-of-place builds with C#

I just finished setting up an out-of-place build system for our existing C++ code using inherited property sheets, a feature that seems to be specific to the Visual C++ product. Building out-of-place requires that many of the project settings be changed, and the inherited property sheets allowed me to change all the necessary settings just by attaching a property sheet to the project. I am migrating our team from C++/MFC for UI to C# and WPF, but I need to provide the same out-of-place build functionality, hopefully with the same convenience. I cannot seem to find a way to do this with C# projects - I first looked to see if I could reference an MsBuild targets file, but could not find a way to do this. I know I could just use MsBuild for the whole thing, but that seems more complicated than necessary. Is there a way I can define a macro for a directory and use it in the output path, for example?
I'm not quite sure what an "out-of-place" build system is, but if you just need the ability to copy the compiled files (or other resources) to other directories you can do so by tying into the MSBuild build targets.
In our projects we move the compiled dlls into lib folders and put the files into the proper locations after a build is complete. To do this we've created a custom build .target file that creates the Target's, Property's, and ItemGroup's that we then use to populate our external output folder.
Our custom targets file looks a bit like this:
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<ProjectName>TheProject</ProjectName>
<ProjectDepthPath>..\..\</ProjectDepthPath>
<ProjectsLibFolder>..\..\lib\</ProjectsLibFolder>
<LibFolder>$(ProjectsLibFolder)$(ProjectName)\$(Configuration)\</LibFolder>
</PropertyGroup>
<Target Name="DeleteLibFiles">
<Delete Files="#(LibFiles-> '$(ProjectDepthPath)$(LibFolder)%(filename)%(extension)')" TreatErrorsAsWarnings="true" />
</Target>
<Target Name="CopyLibFiles">
<Copy SourceFiles="#(LibFiles)" DestinationFolder="$(ProjectDepthPath)$(LibFolder)" SkipUnchangedFiles="True" />
</Target>
<ItemGroup>
<LibFiles Include=" ">
<Visible>false</Visible>
</LibFiles>
</ItemGroup>
</Project>
The .csproj file in Visual Studio then integrates with this custom target file:
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="3.5" ... >
...
<Import Project="..\..\..\..\build\OurBuildTargets.targets" />
<ItemGroup>
<LibFiles Include="$(OutputPath)$(AssemblyName).dll">
<Visible>false</Visible>
</LibFiles>
</ItemGroup>
<Target Name="BeforeClean" DependsOnTargets="DeleteLibFiles" />
<Target Name="AfterBuild" DependsOnTargets="CopyLibFiles" />
</Project>
In a nutshell, this build script first tells MSBuild to load our custom build script, then adds the compiled file to the LibFiles ItemGroup, and lastly ties our custom build targets, DeleteLibFiles and CopyLibFiles, into the build process. We set this up for each project in our solution so only the files that are updated get deleted/copied and each project is responsible for it's own files (dlls, images, etc).
I hope this helps. I apologize if I misunderstood what you mean by out-of-place build system and this is completely useless to you!
Is there a way I can define a macro for a directory and use it in the output path
Have you looked at the pre-build and post-build events of a project?
Actually, pre-build and post-build events seem to be solely a place to add batch-file type commands. This would not help me to set up standard build directories for our projects, unfortunately. And having these events create batch files seems like a very 1980's approach for a modern language like C#, IMO.
After digging some more, and experimenting, I have found that you can add an <Import> directive into your .csproj file. When you do this, the IDE pops up a warning dialog that there is an unsafe entry point in your project - but you can ignore this, and you can make it not appear at all by editing a registry entry, evidently. So this would give me a way to get the variables containing the directory paths I need into the .csproj file.
Now to get the Output Path to refer to it - unfortunately when you add a string like "$(MySpecialPath)/Debug" to the Output Path field, and save the project, the $ and () chars are converted to hex, and your file get's put in a Debug directory under a directory named "$(MySpecialPath)". Arrgghh. If you edit the .csproj file in a text editor, you can set this correctly however, and it seems to work as long as the <Import> tag appears before the <PropertyGroup> containing the Output Path.
So I think the solution for me will be to create a standard OurTeam.targets MsBuild file in a standard location, add an installer for changing the registry so it doesn't flag warnings, and then create custom project templates that <Import> this file, and also set the Output Path to use the properties defined in the OurTeam.targets file. Sadly, this is more work and a less elegant solution than the property sheet inheritance mechanism in C++.

Categories

Resources