I'm attempting to implement a C++ DLL (of my own creation) that uses the Intel Performance Primitives in a C# forms application. I'm getting a "DLL Not Found Exception" when I attempt to run the program. One possible reason put forward in other posts on this site is that there are dependent DLLs that must be referenced and in fact after downloading DpendencyWalker I found that my DLL uses "IPPS-7.0.DLL".
My problem is that it is unclear to me how to reference these dependent DLLs. I've added the IPPS-7.0.DLL containing folder to referenced paths as well as added references to the "IntelCppOptPkg" and "IntelLibOptPgk" assemblies but this has not solved the problem.
So, am I correct in believing this is the problem? And if so, how does one reference a depedent DLL in managed code?
Thank you.
You don't reference them, they are not .NET assemblies. You just need to make sure that the DLL(s) get copied to your build directory. Easiest way to do that is with Project + Add Existing Item, select the DLL from wherever it was copied. Then select the added file and in the Properties window set Build Action = Content, Copy to Output Directory = Copy if newer. Checking-in the DLL(s) in source control is generally a good idea btw.
Managed code can not reference unmanaged dll the same way it references managed assemblies. Managed references actually change the meta data of your assembly:
The compiler records static
references in the assembly manifest's metadata at build time.
...
The preferred way to reference an assembly is to use a full reference,
including the assembly name, version, culture, and public key token
(if one exists).
Native dlls simply don't have this .NET meta data associated with them. They have to be copied manually in the Post Build step or during deployment. There is a workaround but I don't think it will work if your managed app is platform independent (Any CPU) and you have x86 and x64 versions of unmanaged dlls.
Related
What is the ref folder when compiling .NET 5.0 application?
I mean this one:
[project_path]\bin\Debug\net5.0\ref\
These are so called Reference Assemblies (assemblies that only contain the public interface of an assembly), these help speed up the build process, since projects that depend on this one will be able to see that there is no reason to recompile, even if the innards of the assembly have changed, because outwardly it's still the same.
These Reference Assemblies need to look the same as the real thing from the outside. Hence, they have the same filename, assembly name, assembly identity and everything. This allows the build system to use them as a substitute for the real thing. And since these assemblies don't have any of the implementation details, they only change when the interface of the contents changes. Due to these facts, they can't live in the same folder as the actual build output, and this is the reason for the extra ref folder. MsBuild will use these reference assemblies automatically to speed up the build process (at the expense of generating and comparing the reference assembly each time the compiled code results in a new project output and a few files in the output directory).
If your project isn't referenced by other projects, you don't get any benefits from these reference assemblies (if you don't hand them out to 3rd parties that is). And you can turn off this feature by adding this property to the project file:
<PropertyGroup>
<!--
Turns off reference assembly generation
See: https://learn.microsoft.com/en-us/dotnet/standard/assembly/reference-assemblies
-->
<ProduceReferenceAssembly>false</ProduceReferenceAssembly>
</PropertyGroup>
After changing the setting, make sure you clean your build outputs.
These reference assemblies can also be used to allow people to compile projects to work with your system, without having to install/redistribute the actual compiled assemblies that run on your server. This way people can develop extensions, plugins, or clients for your application without having to give them access to actual implementation. This can help protect your intellectual property, since .NET assemblies are easy to decompile.
See also:
https://stackoverflow.com/a/58911152/736079
I have a solution with quite a few projects in it and several dependencies to external DLLs. While trying to build a x64 version of the solution, I found that when building one project several libraries are copied into the output directory which are not mentioned in the project's references or anywhere else within the solution. I figured out that there is a collection of file names called _CopyFilesMarkedCopyLocal, which contains these DLLs. In the concrete case the copied library was used indeed, but it is a x86 library, which overwrites the existing x64 file in the output folder. How does a DLL, which is not mentioned in any project of the solution, become part of this collection? Can some referenced DLL induce further implicit references? Can I control this behavior?
Update: In the x86 build the set of file names contained in _CopyFilesMarkedCopyLocal is what I expected, namely one reference explicitly mentioned.
I have a solution that includes several projects. A few are libs that are building dll's used in my main project in this solution.
My main project builds with output type console application.
This all works fine.
When i change the build output type to a class library (since i want to use this project as a plugin eventually). The project will still build, this time to a dll.
When i use this plugin in an application where i use it as a dll however, it will run up to a certain point where it's trying to load a type defined in an external dll (so NOT built by my solution) and throw the exception:
Could not load type 'externalinterface' from assembly 'externallib, version=3.0.0.0, Culture=neutral, PublicKeyToken=null'.
The dll's are all in the correct folder,etc.
Also worth noting, the plugin is tested in another location than where i built it. The executable still works on this location, the dll/plugin does not. Same amount of dll's in their folders etc.
EDIT: I already used ILSpy (dll inspector) to open the actual dll that is being referenced (so externallib in the errormessage) and checked if 'externalinterface' was present and it is.
EDIT2: RESOLVED! The program that loaded my plugin was loading the same dll that caused the exception. The dll it loaded was of another version than the one i loaded.
Check whether the type externalinterface is present in the referred dll.
You didn't include the details of the exception the application is throwing. However, based on the message you gave, it appears your assembly does not have a strong name. If the application attempting to load your assembly as a plugin does have a strong name, then .NET will require all assemblies loaded by it also have a strong name, so you need to configure your assembly to have a strong name before continuing.
Maybe some supported dll's which is used by the 'externalinterface' is missing in the target machine. In the target machine, check is all the necessary dll's are present in the output folder.
Or blindly copy paste all the dlls in the output folder from the machine where the code is working to the target machine where you have the problem. After this, if the code is working in the target machine, then try to analyze which supporting dll you are missed to copy.
I have an application written in C# which interfaces with some custom hardware using a vendor supplied .Net assembly. The .Net assembly in turn loads another DLL at run time. I can add the vendor supplied assembly to my project but when I run it, the vendor assembly complains that it can't load the required DLL. I can work around this for the moment by copying the DLL to the bin\Debug and bin\Release folder.
The problem is that I will need to distribute this application to clients at some point and they will not have this DLL in place. I can't see how I can make the solution require it; I can't add it as a reference since I get the error "A reference to foo.dll could not be added. Please make sure that the file is accessible, and that it is a valid assembly or COM component."
I can't convert the DLL to a .Net assembly using TlbExp, it gives an error "The module was expected to contain an assembly manifest."
I thought if I published the application via "click once" that I could declare the dependency there but I don't see any way for this either. I also tried adding it as a file resource but this didn't seem to help.
I can see other questions on SO relating to how to invoke functionality in an external DLL but in this case, I just need a way to bundle the DLL with the project.
Thanks.
Indicates that the attributed method is exposed by an unmanaged dynamic-link library (DLL)
The DllImportAttribute attribute provides the information needed to call a function exported from an unmanaged DLL. As a minimum requirement, you must supply the name of the DLL containing the entry point.
For further reference go here
Link to Review
You could add the dll as a resource, write it out as a byte[] to a file on loading, and do an Assembly.Load() at runtime for deployment.
You might have to use an AppDomain.AssemblyResolve Event to make sure the assembly resolves in case of multiple versions.
you could add both (all) of the dlls in your project as references and mark them as "copy local". That should do it unless the first DLL expects the second DLL in a specific place.
I have created a dll that will be used by multiple applications, and have created an installer package that installs it to the program files, as well as adds it to the Global Assembly Cache.
The dll itself uses log4net, and requires a xml file for the logging definitions.
Therefore when the installer is run, the following files get copied to the install directory within program files:
The main dll that I developed
- The Log4Net.dll
- the Log4Net.xml file
I am now experiencing a problem. I have created a test console application for experimentation. I have added my dll as a reference, and set the 'local copy' flag to false.
When I compile the test console exe however, I noticed that it has copied the log4net.dll and log4net.xml files to the bin directory. And when running the test console, it appears that it will only work if the log4net.dll is in the same directory as the exe. This is dispite the fact that the test console application does not use log4net, only the dll that was added as a reference does.
Is there some way to have it so that the log4net.dll & xml files used will be the ones that were installed to the program files, rather than any application needed to copy over local copies? The applications that will be using my dll will not be using log4net, only the dll that they are referencing uses it.
Many thanks
Don't install into the Global Assembly Cache! Even if your library dll is used by multiple applications each should have it's own local copy. Otherwise you get into a whole world of pain for saving a few KB of disk space.
Always copy the required dlls locally. If you are really sure that the application won't need it you can simply delete the unnessesary dlls later or don't include them in the installer. But if your application will call ANY reference there it will crash at runtime. So best option is to leave them there (after all they WERE referenced for a reason).
No, it's not possible (at least not without much efford) to have .Net load dlls from arbitrary locations on the disk. And it should be this way (look up DLL-hell if you want to know why).
I suspect your problem is the configuration. You must use fully qualified names if you want it to work from the GAC. As per the documentation at http://logging.apache.org/log4net/release/faq.html:
"When loading an assembly from the GAC the fully qualified assembly name, including the version, culture and public key must be specified. This is in the standard syntax supported by System.Type.GetType. See the next FAQ on how to get the version and public key for an assembly."
I managed to resolve this by adding Log4net.dll to the GAC as well. It will now run without needing a local copy the dll.
It does however require a local copy of the XML file, to correctly log.