I have a .Net Core 3.1 console application that loads plugins. One of my plugins connects to Sqlite and so it has a Nuget dependency on Microsoft.Data.Sqlite. However, I'm getting a missing DLL exception from the console app when loading/running the plugin because the following path doesn't exist:
MyConsoleApp\bin\x86\Debug\netcoreapp3.1\runtimes\win-x86\native\e_sqlite3.dll
I also have an MsTest project which tests this Sqlite plugin project. It does not have the same problem. Apparently the runtimes folder and contents will automatically exist if a Visual Studio project (1) is some kind of executable and (2) has a pertinent Nuget or project reference.
Following those rules, two of my three Visual Studio projects do not have the runtimes folder:
The plugin has a Nuget dependency on Microsoft.Data.Sqlite, but does not have the runtimes folder because the plugin project is a DLL...not an executable.
The MsTest project which tests the Sqlite plugin does have the runtimes folder and contents because (1) it it is a type of executable and (2) it has a project reference to the plugin project (which in turn references the Nuget package).
The main console app is an executable, but (intentionally) doesn't have a project reference to the plugin. Thus it does not have the runtimes folder.
How do I solve this? As a hack I have simply copied the missing DLL into the output target directory for the console app.
Also, if I add a project reference from the console app to the plugin, this problem is solved. But, as stated, I don't want the console app to have project references to any plugins. Plugins should be discovered dynamically. I think fixing this may have something to do with creating a nuspec file. However, the documentation for nuspec files has no commentary about addressing this.
.Net Plugin Architecture Not Working with Nuget
Just as you said that, the lib plugins project which references Microsoft.Data.Sqlite does not have the runtime folder and when an exe project reference the lib plugins project, the runtimes folder will be copied into the the exe project's output folder.
Solution
1) Since you do not want to reference the lib plugins project for the console project, you can just do a copy task in msbuild from the MsTest project's runtimes folder.
Write this target in the xxx.csproj file of Net Core 3.1 console application:
<Target Name="Copy_Runtimes" AfterTargets="Build">
<ItemGroup>
<CopyItems Include="..\MsTest\bin\Debug\xxx\runtimes\**\*.*" />
</ItemGroup>
<Copy SourceFiles="#(CopyItems)" DestinationFolder="$(OutputPath)runtimes\%(RecursiveDir)%(Filename)%(Extension)')"></Copy>
</Target>
2) Besides, you can also install the nuget package called sqlite in the net core 3.1 console application, and this package only contains the runtimes folder and does not include other com dlls for using.
It is actually a pure service package for providing runtimes folder.
You can install this package in your console project directly and if you are not satisfied with this, you can only try solution 1 to solve the issue.
Related
I'm working on a C# application which requires integrating with another company's software. I have isolated all of the code that is tightly coupled to this integration in a single C# project. This way, if the company changes something with their integration, I only have to change code in this one project. The project is a non-executable class library (Project A).
One weird/annoying part of this integration though is that it involves manually copying compiled .dll files from the company's SDK into the bin directory of the project after the project is built. I can't just use a nuget package or something similar. While annoying, I have automated it with a post-build script and it works well enough for that specific project.
I then reference this project/class library from an executable class library, such as a .NET Framework Console project (Project B).
Now I have a problem:
Build Project A
Runs post-build script XCopy C:\CompanyIntegration\Autofac.dll "${TargetDir}".
Compiles without any issues.
Build Project B
Compiles Project A, copies .dlls from Project A bin to Project B bin.
The copied Autofac.dll from Project A overwrites one installed via a nuget package.
The build throws an exception because it expected a different Autofac.dll.
How can I tell the build process to differentiate between these two different Autofac versions/dlls?
Why are the company integration .dll files copied from the bin folder of Project A to the bin folder of Project B in the first place?
If a .NET 462 project references a .NET Standard 2.0 dll the dependencies are not copied to the output bin folder.
It works correctly when the .NET Standard 2.0 project is referenced as <ProjectReference /> and <RestoreProjectStyle>PackageReference</RestoreProjectStyle> is added to the .NET 462 project.
My .NET Standard 2.0 project lives in a different solution and therefore cannot be added as project reference.
Is there a solution to this problems, that maybe takes the deps.json in the bin folder of the .NET Standard 2.0 project into account?
Or is the only solution to add the .NET Standard 2.0 project to all solutions, where projects have references to it?
If you cannot add the project as a project reference, consider using NuGet to consume a built package (and the contained dependency graph).
At the time of writing, .net standard projects and their dependencies cannot be referenced from a set of files (like produced by dotnet publish on the .net standard project) since the graph of NuGet packages needs to be resolved for the target executable project's framework (core, .net framework, uwp, ..) and certain build logic that needs to run during build & publish for the resulting executable project is not being run for .net standard projects.
I have a C# class library project in VS 2017 that I'm trying to make work with Nuget packages in a somewhat strange release environment.
The project has a packages.config with standard Nuget packages such as EntityFramework 6.2.0 for example.
The project compiles fine, but the release environment is setup so that only the class library project DLL itself is deployed (no dependent DLLs).
The class library DLL needs to resolve the DLL references in a completely different directory such as C:\Dependencies, instead of the deployment location C:\ClassLibraries.
How can I resolve the dependencies that are in a completely different folder after release?
Edit: I already tried this HintPath Exists trick posted here, but it didn't work:
.csproj multiple hint paths for an assembly
Edit 2: I don't have access to the EXE that calls this DLL or the app.config associated with the EXE that calls this DLL.
I have created a system which loads dynamically a library and executes it's main class.
Everything works perfect, the problem I have is how to publish this DLL with all it's dependencies. As no executable project is referencing it I have to manually retrieve the dependencies: try to load the library, check the needed DLL's, go to the NuGet cache folder, copy the libraries, try again, check if it complains about more dependencies and so on until it has all the required libraries.
This is a true pain and I haven't found any information on how to do this, is it possible or am I stuck with this?
The library is a .net standard 2.0 library, I did this before with .net classic and the output folder always contained all the required libraries even the ones comming from a NuGet package, but with .net standard something has changed and now only libraries from referenced projects are being copied, no referenced NuGet package is being copied to the output folder.
Cheers.
Try:
dotnet publish
All the dependent libraries should be copied to the publish output folder.
At the time of writing, it looks like it's by design and there's quite some fuss and confusion about it, see logged issue on GitHub.
Moreover, when publishing a NuGet package for project A referencing project B,
B becomes a NuGet dependency in A; B's assemby is not included in A's NuGet package.
I deal with it by publishing my own NuGet packages.
I only don't like it to have a NuGet package for project B if that one is only relevant to be used with/by project A, as it will appear seperately in my NuGet feed.
TLDR: Convert your Class Library project into an Application, publish the application, and use application DLL as a library.
The long of it:
I tested this approach by deploying a full build with a plugin with many external dependencies to Ubuntu 18.04 and it ran perfectly.
Create a new project of type Console Application instead of Class Library. Put all your library code files into the Console Application and add the dependencies. Get rid of your original Class Library project (you don't need it anymore). Finally, publish the Console Application. You will get a DLL with all of the dependencies. You can use this DLL like any other DLL.
I suggest naming the console app project with "Library" on the end of it and adding a README just to document its not really an application even though the project is configured to build as one.
Is it possible to make Visual Studio to copy all dependencies of referenced projects into the output path?
Example
In the Solution, Project A (Library, .NET Standard) defines some functions and is dependent on Library L1 (via NuGet) and Library L2 (local .dll, referenced and copied to project)
Project B (Console Application) references Project A.
When building B, The output folder contains all direct dependencies of B and A.dll. L1 and L2 are not available in the output. Therefore, the program does not work correctly.
How can I force VS to copy also L1 and L2 to the output of B?
The only way I found so far is packing A as NuGet, but this seems to be unnecessary overhead and uncomfortable. I think I am just forgetting something everyone else seems to know...
Edit (clearifying Example)
My solutions consists of two projects.
Project MongoWrapper
.NET Standard 2.0 class Library
depends on NuGet MongoDB.Driver package
Actually uses this dependency (no zombie dependency)
Project ConsoleUser
.Net Framework 4.6.1 Console Application
References MongoWrapper project
Actually uses MongoWrapper
Observation
When debugging the ConsoleUser application, it compiles and starts. During runtime, when it calls a method in the MongoWrapper which uses the MongoDB.Driver, the application crashes, as the MongoDB.Driver dependency was not copied into the output folder of the ConsoleUser.
How to fix this?
The problem was introduced by the usage of .Net Standard library and a .Net Framework application.
TLDR
Open the .csproj file of the .Net Framework project with a text editor. Inside the first PropertyGroup add the line
<RestoreProjectStyle>PackageReference</RestoreProjectStyle>
Save the file, reopen Solution in Visual Studio and perform Clean & Build
Dependencies in different project file versions
.Net Framework projects use an old version of the .csproj project files. References/Dependencies are stored in the additional packages.configfile. By default, building a .Net Framework project makes the system to search for a packages.config file in the referenced projects. If no such file is found, the build task treats the referenced project as having no dependencies. Therefore, in the example, the MongoDB.Driver library is not added.
By adding the proposed line in the .csproj project file, the build task searches the project file of the referenced project for dependencies, where they are stored in .Net Standard project files.
.Net Core projects by default search for the newer project file structure.
The default behavior for new projects can be set in the Options -> NuGet -> General -> Package Management
Is it possible to make Visual Studio to copy all dependencies of referenced projects into the output path?
Yes.
This is what publishing the application does - it prepares the application for deployment. When you publish, it will include all of the dependencies that the application requires to run in the output.
Use the Publish tool to deploy to a local folder. The exact options available depend on your app type. In Solution Explorer, right-click your project and choose Publish, and then choose Folder. For more information, see Deploy to a local folder.
Tutorial: Publish your Hello World application with Visual Studio 2017
Also see: .NET Core application deployment.