Background info (might be relevant):
Using Unity 2017.2 with "Scripting Runtime Version" set to "Experimental (.NET 4.6 equivalent)"
Writing code in Visual Studio 2017 (not MonoDevelop)
I have a Unity project that makes direct use of a third-party DLL ("library A"), which I've added to the project's Assets folder. Library A depends on another DLL, "library B", which I've also added to the Assets folder. Library B is not used by any scripts in the Unity project. Both libraries A and B are written in C# and target .NET 4, i.e., they're both managed code.
Once added to the Assets folder, both libraries A and B are listed under "References" when the project is opened in Visual Studio and "Copy Local" is set to "True" for both (although I don't know if Unity uses that property).
However, when running the project in the Unity editor, various calls to library A raise exceptions that indicate that library B isn't available. The only way I've been able to get it to work is by placing a copy of library B in C:\Program Files\Unity\Editor (the directory containing Unity.exe, the Unity editor executable).
I've used libraries A and B in other, non-Unity projects and never had any issues (Visual Studio copies them both to the output directory as long as they're referenced). Am I missing a Unity-specific step that's necessary to tell it that library B is required?
I ran into this same issue today, and here's what fixed it for me: In the Unity editor, navigate to where the library B is located, select the library, and on the Inspector window under "Plugin load settings", enable the "Load on startup" checkbox. I suppose this is needed because no Unity scripts are directly calling library B.
I just wanted to share how i get this done. I'm using Unity 2019.2.10f1 by the way.
I have many of my own and third party managed dll files in my project, and I copy them all to ProjectFolder\Assets\Resources\
and I've never had any problem calling out to any of the libraries, or those libs calling each other.
Maybe the issue is that since your second library (library B) is not referenced by any scripts, Unity is not bundling it and making it available at debug/runtime.
In my experience, I have found that if you want something to be retained in your build, (any unreferenced assets that may be consumed dynamically at runtime), stick it in the Resources subfolder of Assets.
A second option may be to construct some dummy call to the second 'Library B' (that does nothing, perhaps construct and dump), so that Unity thinks that it is needed and includes it in your build.
Not sure if that helps, but Good Luck!
Unity actually has a special folder called "Plugins" directly under the Assets folder that you can use. This will allow you to add references to dlls made outside of Unity and link against them. You can even have them sorted by targets!
Assets/Plugins/x86
Assets/Plugins/Android
...
The plugins accepted are all these following extensions: .dll, .winmd, .so, .jar, .aar, .xex, .def, .suprx, .prx, .sprx, .rpl, .cpp, .cc, .c, .h, .jslib, .jspre, .bc, .a, .m, .mm, .swift, .xib, .dylib, .framework, .bundle, .plugin
Unity 2020.3 Plugins Documentation
Related
At the moment of creating a project of type "Library of Classes, usually one can generate a dll when compiling, but how could I generate a dll without losing others that I already have included?
I explain with an example: It turns out that Nuget downloaded an S22.Imap dll with the one I worked with, later I generated the dll in the traditional way that I explained in the beginning, but when I wanted to work with dll in another computer, I got errors that were not I found functions that contained the S22.IMAP dll. So to solve this problem, I had to copy the dll of my project, S22.IMAP in an additional way in a specific path of the other computer.
My question is:
How could you generate a dll that includes the ones included in the project you were working with?
All the referred 3rd party dlls (S22.Imap.dll in your example) will be copied to the output folder together with your own dll file (let's say a.dll) when you build your project. That means you should always copy them together (S22 + a.dll) to the place you want to refer them, on another computer/folder/place.
If you really want to make them only one file (although it is not recommended), you can set the S22 one as some "nested resource". Then you will get only one a.dll file and the S22 one is inside the a.dll. See below page for some reference:
Embedding one dll inside another as an embedded resource and then calling it from my code
AND, ILMerge is some tool that can help you do so.
In general, you don't. A DLL is a dynamic linked library, and you would normally only combine static libraries during a build. Here is an answer on the difference between static and dynamic linking.
Typically you would include all the DLLs you need in the installer package. If you use Visual Studio to create the installer, it can detect the dependencies for you. When you run the installer, all of the necessary DLLs are deployed. Nearly all commercial .NET software follows this pattern.
It is possible to merge an assembly into another assembly using a tool called ILMerge. This would be a very unusual thing to do, and could cause issues with intellectual property and code signing, so it is not recommended.
I would like to expose some objects and classes for DLL plugins for a Unity 5 game.
The plugins(DLL/.net assemblies) are loaded at runtime later. But these DLLs need to access classes and objects already created by the main game.
I use the Assembly.LoadFrom() method to load the plugins DLLs: Use assembly class without the assembly object
Since there does not seem to be any header files in C# as in C++, how do I expose the game program's(.exe) classes to plugins?
Reference UnityEngine.dll and your Assembly-CSharp.dll
Whenever the Unity editor compiles C# code, it most often generates one DLL (it generates more if you're using UnityScript, for example) - that DLL is called Assembly-CSharp.dll, and it gets stored in the Library/ScriptAssemblies folder of your Project files in the Editor.
Just like any other DLL, you need to reference it. As it uses the Unity API, you'll need to reference UnityEngine.dll too, which can be found in, for example, c:/Program Files/Unity/Editor/Data/PlaybackEngines/androidplayer/Managed/UnityEngine.dll
For most platforms, UnityEngine.dll is the same (i.e. the above is using the one which gets compiled into an Android build), so it doesn't matter too much which one you use, however, you should use the one for your target platform.
Platforms this doesn't work for
As a side note, keep in mind that DLL loading doesn't work on a variety of platforms - iOS and WebGL as well known examples (because they don't run .NET IL at all).
After a build has been made
You'll want to make sure you reference the correct DLL after a build has been made. With a Windows standalone, for example, you'll easily find it again within the built *-Data folder. On android, it can be extracted from the APK too.
In Summary
In general, when you build the game, you'll need to recompile your DLL (referencing the latest Assembly-CSharp.dll).
As a side note, you can also precompile your whole codebase into a DLL and use that in your project, but keep in mind that this breaks #preprocessor directives so you have to rebuild it when you swap platforms. However, at least you have full control over when that DLL rebuilds (and as a result, when your referencing ones need to).
We have an app A that has a reference to an assembly B that contains some static methods. Assembly B is in the same Visual Studio solution as app A.
We want the users of our app A to be able to write plugins. They build the plugin (at present) by creating a new Class Library solution in Visual Studio, getting the Nuget Package for app A, and adding a reference in their plugin solution to assembly B, so that the plugin code compiles.
They do not need to test their plugin, which is why the code just needs to compile, although it would be nice if they could debug their code when running it in app A.
Once their code has compiled, the DLL for the plugin is put in a share and given to a different team (bureaucracy I know) who put it with the rest of app A's DLLs.
I would like the plugin DLL to use the assembly B DLL that is with all of app A's DLLs.
When I run app A, the Activator class picks up the plugin DLL and correctly creates an instance, but as soon as one of the static methods from assembly B is called, the plugin throws a MissingMethodException.
Things I have tried:
The plugin solution definitely works fine if you create it and compile it within application A's Visual Studio solution.
App A uses framework .Net 4.5, assembly B uses framework .Net 4.0, I have tried building the plugin with both frameworks without success.
The "Specific Version" of the reference to assembly B in the plugin solution was false in all cases tested.
I would welcome immediate solutions to this problem but also broader architectural suggestions on how to get these plugins to work. I apologise if there is a duplicate question of this, I couldn't find one.
For starters you can use "Dotpeek" to decompile dll and see if the method defination exactly matches.
It's a free software available to decompile dotnet libraries.
If you don't have access to .pdb file then i would recommend using "dotnet reflector",or "IL Spy" it will decompile without pdb files.
Also do make sure you are referencing project in visual studio not the output dll.
I managed to fix my problem as follows:
Although the plugin only directly used static methods in Assembly B, these static methods actually made a chain of calls to various OTHER assemblies.
Instead of just adding a reference to Assembly B in my plugin, I did a Nuget command:
Install-Package -Id AppA -ProjectName Plugin
And this downloaded the latest AppA to the packages folder and added a reference to EVERY dll of AppA.
Like before, it compiled, but this time when I dragged the plugin dll into the AppA bin folder, the plugin code ran without throwing an exception.
I have a C# project which builds a library DLL, myLib.dll. This DLL has a dependency on a 3rd party DLL, dep.dll (which I provide but do not build).
I want others to be able to use my library by adding my project to their solutions and referencing it. Adding my project as a reference automatically copies myLib.dll to the Target directory of their app, but of course dep.dll is not copied with it.
Bear in mind that I have no control over where my project is in their code tree, and the DLL can't know where it was copied from.
The only solution I can see is to force the user to add a build event which copies dep.dll to their target directory. We can't assume users can create environment variables.
This is very undesirable for several reasons (it's not really one dependency - I simplified things, I don't want them to have to be concerned about the dependencies in my project, and it's very fragile - adding an extra dependent DLL to my project would require everyone to update their build scripts).
I can't load the dep.dll directly as I don't know where it is - my build scripts can copy it to the same target directory as myLib.dll but the actual version of myLib.dll they run will have been copied somewhere else.
I also can't make dep.dll a reference directly (probably because it's not a .NET assembly). I just get "Error loading code-completion information for dep from dep.DLL. Format of the executable (.exe) or library (.dll) is invalid".
So is there any way to have the dependent DLL just seamlessly copied with myLib.dll when a client builds their application? [I'm using Sharp Develop if it matters.]
Can you add dep.dll to your projects root folder as a file like a .cs file. Set the Build Action to None and Copy to Output Directory to Copy if newer.
Currently I am creating Grasshopper 3D plugins. I was originally using the C# DateTime library for my time zone needs, but found NodaTime for how extensible and convenient it is. Fell in love immediately.
While creating Grasshopper 3D components, I referenced my assemblies via:
Grasshopper 3D components that are written in C# in Visual Studio compile as class libraries (so there's no console output). So for my preliminary development, I tested NodaTime via a console app. Same configuration, where I used the same method, same assembly, same reference adding -- the console application works just fine. But once I used that method in my Grasshopper component, I get this error:
The things I have personally tried:
Re-opened my Visual Studio and project.
Removing the references and using statements, and adding it again.
Copying [all three] portable .DLLs to my /bin/ directory
Copying [all three] portable .DLLs to my/Libaries/ directory. The /Libraries/ directory are where the Grasshopper 3D component DLLs reside (loaded into Grasshopper for use).
Copy [all of the assemblies] of the NodaTime folder into my /Libraries/ directory.
Setting CopyLocal of NodaTime to true. And to false.
Deleting .PDBs
Suggested by another user, maintained my dependencies via NuGet.
I have indeed read most if not all of the could not load file or assembly Stack Overflow threads, and have checked solutions in the Grasshopper forums.
What could be the issue?