Visual Studio 2022 place referenced dll into subdirectory of bin folder - c#

I have created a c#-project in Visual Studio 2022 which is using the nuget-package "Microsoft.Data.SqlClient".
This package brings along about 60(!) dll, so that my \bin\release folder is now really full.
To get more clarity in this folder, I was wondering if these dll could be placed in a subdirectory of \bin\release, for example \bin\release\dll.
I'm also wondering why there are *.xml and *.pdb files genereated for every *.dll file in \bin\release.
Could this be suppressed?
Thanks for any suggestions!
Tobias

As you said, you are using .net framework, you can refer to the following steps to achieve your requirement:
First, you can add post build event in property of the project to move the DLLs into lib folder:
You can refer to this command line in post build event:
ROBOCOPY "$(TargetDir) " "$(TargetDir)lib\ " /XF *.exe *.config *.manifest /XD lib logs data /E /IS /MOVE if %errorlevel% leq 4 exit 0 else exit %errorlevel%
Then add this code in your App.config file:
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<probing privatePath="lib" />
</assemblyBinding>
</runtime>
It looks like this:
Finally build the project it will be clean in the folder and the .exe file works fine.

You hardly will be able to run your executable without the dependencies. Regarding the .pdb debug info files, a great answer is provided here: Release generating .pdb files, why?
Good luck! 🤞

I think you can use the Probing element
Something like this
<configuration>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<probing privatePath="bin;bin2\subbin;bin3"/>
</assemblyBinding>
</runtime>
</configuration>

Related

DLL in NuGet package not appearing in build output folder

We have a NuGet package that was created by ourselves and is hosted on an in-house repo. We've been using it for several years in a .Net Framework 4.x solution. The package contains a .Net4.x assembly (a class library, referenced by code in the solution), two "native" DLLs, and a handful of .c files. When the solution builds, every file in the package gets copied to the build output folder, which is what we expect.
I've now migrated this solution to .Net6 and referencing the same package, but the build behaviour is different. Here, the solution builds successfully but none of the files in the package get copied to the build output folder. Instead, the two native DLLs and .c files get copied to the root folder of the referencing project (also showing up in the VS solution explorer window). The .Net assembly (TspAdqAcquisition.dll) does not appear in the project root folder, or anywhere else for that matter.
What's going on?
This is the nuspec file (from the "library" solution where the Tsp...dll and other files reside):
<?xml version="1.0" encoding="utf-8"?>
<package >
<metadata minClientVersion="2.5">
....
</metadata>
<files>
<file src="x64\Release\*.c" target="build" />
<file src="x64\Release\glew64.dll" target="build\glew64.dll" />
<file src="x64\Release\glut64.dll" target="build\glut64.dll" />
<file src="x64\Release\TspAdqAcquisition.dll" target="lib\net451\TspAdqAcquisition.dll" />
<file src="x64\Release\TspAdqAcquisition.dll" target="lib\net\TspAdqAcquisition.dll" />
<file src="x64\Release\TspAdqAcquisition.dll" target="lib\net6.0\TspAdqAcquisition.dll" />
<file src="x64\Release\TspAdqAcquisition.dll" target="lib\net6.0-windows10\TspAdqAcquisition.dll" />
<file src="x64\Release\TspAdqAcquisition.dll" target="lib\net6.0-windows11\TspAdqAcquisition.dll" />
</files>
</package>
Edit
I've figured out why the two native DLLs and .c files weren't being copied to the build output folder. The NuGet package in question is referenced by a class library project (net6.0 TFM rather than net6.0-windows), so these particular files were ending up in a separate \net6.0\ build output folder, rather than the \net6.0-windows\ build output folder that the rest of the solution ends up in. Once I'd referenced that class library project by one of the WPF projects, these files appeared in the correct build output folder.
However the TspAdqAcquisition.dll assembly still isn't being copied to (either) build output folder.
Edit 2
I'm now able to get the TspAdqAcquisition.dll assembly to copy to the build output folder by including this line in the project file:
<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
I had to put this in the WPF project file to ensure that the DLL is copied to the correct (\net6.0-windows) build output folder. If I add the above line to the class library project file referencing the NuGet package then the DLL ends up in the wrong (\net6.0) build output folder.
It's all starting to feel a bit hacky for my liking...
My last remaining question then is whether it's possible to prevent those native DLLs and .c files from being "unpackaged" into the project folder and cluttering up the solution explorer window? Why doesn't this happen in VS2019?
It seems you don't have a .targets file in the nuget package. I'm not sure whether that's the "normal" way of how this should be done, but that's how I copy native binaries to the output.
So one possible way to get this to work correctly, is to create a <packagename>.targets file in the build folder of the nuget with content such as:
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Target Name="CopyFilesToTargetDirectory_MyPackageName" BeforeTargets="Build">
<ItemGroup>
<FilesForTargetDirectory_MyPackageName Include="$(MSBuildThisFileDirectory)\..\tools\**\*.*" />
</ItemGroup>
<PropertyGroup>
<TargetDirectory_MyPackageName Condition="'$(TargetDirectory_MyPackageName)' == ''">$(TargetDir)</TargetDirectory_MyPackageName>
</PropertyGroup>
<Copy SourceFiles="#(FilesForTargetDirectory_MyPackageName)"
DestinationFolder="$(TargetDirectory_MyPackageName)\%(RecursiveDir)"
SkipUnchangedFiles="true" />
</Target>
</Project>
and then, move the native libraries from the build folder to either the tools folder (as in the example code above) or the lib\native folder.

Keep local copy of Nuget Package in VS Code

In Visual Studio Code, i would like to keep a local copy of a referenced Nuget package in the project folder for the case the package will not be available online for some reason in the future.
nuget restore shall still be able to download it from the internet if the local copy is not yet there.
I think thats exactly the behaviour with Visual Studio, but i can't get this running with Visual Studio Code
I think i found a solution myself.
Adding a file called nuget.config with the following content to the project folder does exactly what I wanted. The packages are now put into the local packages folder.
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<config>
<add key="globalPackagesFolder" value="packages" />
<add key="repositoryPath" value="packages" />
</config>
</configuration>

How to i create a custom build directory for my WPA app

I'd like to clean up the generated build of my app so that the app's folder contains a specific folder hierarchy where all of the various automatically included .dll's are placed in a second level folder and not right alongside my .exe
How would i go about doing this in a C# VS2019 solution?
Desired Example structure:
[App]
[Resources]
Newtonsoft.Json.dll
System.Data.SQLite.dll
etc...
[Data]
Data.sqlite3
etc...
Launcher.exe
App.config
After a day of digging and trial and error, the following solution can be used to generate a clean, custom, styled, hierarchy for the build folder.
1) Add 'probing privatePath=MyFolder' to your project's App.config file.
<configuration>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<probing privatePath="MyFolder" />
</assemblyBinding>
</runtime>
</configuration>
2) Add a target node with 'AfterBuild' to your project file. (Open your apps .csproj file in a text editor) Then add one <move> node for each assembly .dll that's just dumped next to your .exe with the source set to the assembly dll you want to move and the destination set to $(OutDir)\MyFolder
<Target Name="References" AfterTargets="AfterBuild">
<Move SourceFiles="$(OutDir)\MyAssemblyClutter.dll" DestinationFolder="$(OutDir)\MyFolder" />
</Target>
Note: Build > Clean won't remove your custom folders or their content after this.
For bonus points (credit to Jason Morse), to ensure that NuGet packages don't dump their debugging .pdf and documentation .xml files into your release build folder, add the following to your project file within the '<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">' node.
<AllowedReferenceRelatedFileExtensions>
<!-- Prevent default XML and PDB files copied to output in RELEASE. Only *.allowedextension files will be included-->
.allowedextension
</AllowedReferenceRelatedFileExtensions>

Where is NuGet.Config file located in Visual Studio project?

I am wondering where is NuGet.Config file located in Visual Studio 2017 project? I tried to create my own NuGet.Config file in the root of the project, but I didn't find any new repositories (NuGet sources). Does some one have any idea?
Here is the file I am trying to achieve for my .Net Core project:
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<packageSources>
<add key="AspNetCore" value="https://dotnet.myget.org/F/aspnetcore-ci-dev/api/v3/index.json" />
<add key="AspNetCoreTools" value="https://dotnet.myget.org/F/aspnetcore-tools/api/v3/index.json" />
<add key="NuGet" value="https://api.nuget.org/v3/index.json" />
</packageSources>
</configuration>
Visual Studio reads NuGet.Config files from the solution root. Try moving it there instead of placing it in the same folder as the project.
You can also place the file at %appdata%\NuGet\NuGet.Config and it will be used everywhere.
https://learn.microsoft.com/en-us/nuget/schema/nuget-config-file
There are multiple nuget packages read in the following order:
First the NuGetDefaults.Config file. You will find this in %ProgramFiles(x86)%\NuGet\Config.
The computer-level file.
The user-level file. You will find this in %APPDATA%\NuGet\nuget.config.
Any file named nuget.config beginning from the root of your drive up to the directory where nuget.exe is called.
The config file you specify in the -configfile option when calling nuget.exe
You can find more information here.
If you use proxy, you will have to edit the Nuget.config file.
In Windows 7 and 10, this file is in the path:
C:\Users\YouUser\AppData\Roaming\NuGet.
Include the setting:
<config>
<add key = "http_proxy" value = "http://Youproxy:8080" />
<add key = "http_proxy.user" value = "YouProxyUser" />
</config>
In addition to the accepted answer, I would like to add one info, that NuGet packages in Visual Studio 2017 are located in the project file itself. I.e., right click on the project -> edit, to find all package reference entries.
no matter where these files are here is a way to edit them via the dotnet CLI
verify 'file' to get current entries:
dotnet nuget list source
add new source:
dotnet nuget add source https://nuget.example.com -n SomeName

Build a project with relative path to dll

I have created a c# project in it I reference system.windows.interactivity.dll.
What I'm wondering is how to set the project up so that when I build the *.exe I get this sort of structure:
Program Folder
program.exe
Libraries Folder
system.windows.interactivity.dll
I have tried a little bit of experimentation by placing a "Libraries" folder under the solution folder, so that it is at the same level as the project folder. This gives a relative path in the csproj file of "..\Libraries\system.windows.interactivity.dll", however this cannot be the solution as when I compile it copies the dll into the debug folder with the exe and it keeps this 'same level' path structure.
How can I alter things so that it places and references the dll in another directory?
[Update]
So I have modified the following in my project:
1: Changed the 'Copy Local' property on reference system.windows.interactivity.dll to False.
2: Added the following code to the csproj file to check if the Libraries folder exists above the Output directory, if not create and then copy over the dll.
<Target Name="BeforeBuild">
<MakeDir Directories="$(OutDir)..\Libraries"
Condition="!Exists('$(OutDir)..\Libraries')" />
<Copy SourceFiles="..\Libraries\System.Windows.Interactivity.dll"
DestinationFolder="$(OutDir)..\Libraries"
ContinueOnError="True" />
</Target>
3. Add the following code to App.config to add another location for the app to search for the dll.
<configuration>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<probing privatePath="..\Libraries"/>
</assemblyBinding>
</runtime>
</configuration>
My Findings:
Upon building the app, all files are exactly where I want them, as in the structure in my original post. When I try to run the exe from the output directory it cannot find the dll.
[/Update]
Using app.config you can tell .NET to probe subdirectories to search for assemblies (.NET needs to know how to find the DLLs when the application runs when they're in a non-standard location):
https://msdn.microsoft.com/en-us/library/823z9h8w(v=vs.110).aspx
<configuration>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<probing privatePath="bin;bin2\subbin;bin3"/>
</assemblyBinding>
</runtime>
</configuration>
You could modify the .csproj file to do a BeforeBuild/AfterBuild task and copy the dll to a subdirectory. However if you really only want this structure for deployment, it would probably be easier to include that as part of the package/installer logic instead of the direct build logic. Typically it's much easier to just let the compiler pick the output destination for your DLLs.
Here's an example of how you'd create the BeforeBuild copy task:
Copy all files and folders using msbuild
You can tell Visual Studio not to copy the DLL to the output folder by setting "Copy Local" to false on the reference.

Categories

Resources