I need to reference two assemblies in my .NET program:
The first assembly, namely ILNumerics, directly references native hdf5.dll library (version 1.8.17) by mean of dllimport("hdf5.dll") platform invoke.
The second assembly, of my own, is a .net wrapper on top native matlab runtime libraries, but this native runtime also internally makes use of native hdf5.dll library (version 1.8.12) [required when working with hdf5 data from matlab side].
Note also that native hdf5.dll library also depends on hdf5_hl.dll and zlib.dll.
I have tried to keep only one version of hdf5.dll library and dependencies and also to set environment variable HDF5_DISABLE_VERSION_CHECK to 2 when starting my application but I can't escape from abrupt crash as I need to use hdf5 handling from both ILNumerics and Matlab runtime sides.
Is there a way I can cheat "dllimport("hdf5.dll")" in ILNumerics assembly to alias some other name ? Note, I don't have the sources, so i cannot hard recompile with dllimport("hdf5_1_8_17.dll"), same for matlab runtime library, I cannot changed anything in it (again third party + native code). What about, in case cheating hdf5.dll name in ILNumerics would be possible, the indirect reference to hdf5_hl.dll from hdf5.dll ?
I guess my only last option is to use load ILNumerics and Matlab runtime assemblies in different applications domains, but then this would be "hell" because I will need to serialize data when calling one or another assembly exposed routine, right ? (I have never worked with separate application domains)
Related
I'm trying to add Windows/System32/Shell32.dll DLL to my project. The issue is, it copies the reference to the directory! Since this is a windows file, it shouldn't have to come with me if I were to deploy my application.
I have tried stopping it from copying to the directory, tried looking for how to embed the resource in the application and even added reference paths to System32. It seems so much more challenging than the program just using the local DLL from the system...
What can I do?
Shell32.dll is a COM component. You should not get a copy of it in your project. What you get instead is Interop.Shell32.dll. Which is a .NET assembly, not a copy of Shell32.dll. It contains the COM interface and class declarations, converted from the type library definition inside Shell32.dll to friendly .NET declarations that the CLR knows how to easily handle.
This is an optimization, it avoids having to make the conversion at runtime. Which is expensive, subject to various options (check the MSDN docs for Tlbimp.exe) and may easily fail because there is no general requirement that the type library is also available on the target machine.
You must deploy Interop.Shell32.dll to the target machine, just like you do with any .NET class libraries you'd use.
Do note that this interop library is no longer needed on .NET 4 and VS2010. Which acquired the "Embed Interop Types" feature. In other words, instead of keeping the interop types in a separate assembly, the C# and VB.NET compilers can now embed them in your program. Very highly recommended, just set the option to True in the Properties window view of the Shell32 reference.
I have third party libs that were compiled as /MTd and /MT respectively. These cannot be changed. I am consuming them using a MT dll.
How can I cross boundaries into /MD dll land in order to satisfy the requires for /CLI and have any hopes of calling these third party libs from C#?
Fairly easy: COM-style. That is to say, do not assume you can pass C++ types (because the C++ libraries differ) but instead pass all data using the native COM mechanism such as BSTR/_bstr_t.
Since version 3.0, .NET installs a bunch of different 'reference assemblies' under C:\Program Files\Reference Assemblies\Microsoft...., to support different profiles (say .NET 3.5 client profile, Silverlight profile). Each of these is a proper .NET assembly that contains only metadata - no IL code - and each assembly is marked with the ReferenceAssemblyAttribute. The metadata is restricted to those types and member available under the applicable profile - that's how intellisense shows a restricted set of types and members. The reference assemblies are not used at runtime.
I learnt a bit about it from this blog post.
I'd like to create and use such a reference assembly for my library.
How do I create a metadata-only assembly - is there some compiler flag or ildasm post-processor?
Are there attributes that control which types are exported to different 'profiles'?
How does the reference assembly resolution at runtime - if I had the reference assembly present in my application directory instead of the 'real' assembly, and not in the GAC at all, would probing continue and my AssemblyResolve event fire so that I can supply the actual assembly at runtime?
Any ideas or pointers to where I could learn more about this would be greatly appreciated.
Update: Looking around a bit, I see the .NET 3.0 'reference assemblies' do seem to have some code, and the Reference Assembly attribute was only added in .NET 4.0. So the behaviour might have changed a bit with the new runtime.
Why? For my Excel-DNA ( http://exceldna.codeplex.com ) add-in library, I create single-file .xll add-in by packing the referenced assemblies into the .xll file as resources. The packed assemblies include the user's add-in code, as well as the Excel-DNA managed library (which might be referenced by the user's assembly).
It sounds rather complicated, but works wonderfully well most of the time - the add-in is a single small file, so no installation of distribution issues. I run into (not unexpected) problems because of different versions - if there is an old version of the Excel-DNA managed library as a file, the runtime will load that instead of the packed one (I never get a chance to interfere with the loading).
I hope to make a reference assembly for my Excel-DNA managed part that users can point to when compiling their add-ins. But if they mistakenly have a version of this assembly at runtime, the runtime should fail to load it, and give me a chance to load the real assembly from resources.
To create a reference assembly, you would add this line to your AssemblyInfo.cs file:
[assembly: ReferenceAssembly]
To load others, you can reference them as usual from your VisualStudio project references, or dynamically at runtime using:
Assembly.ReflectionOnlyLoad()
or
Assembly.ReflectionOnlyLoadFrom()
If you have added a reference to a metadata/reference assembly using VisualStudio, then intellisense and building your project will work just fine, however if you try to execute your application against one, you will get an error:
System.BadImageFormatException: Cannot load a reference assembly for execution.
So the expectation is that at runtime you would substitute in a real assembly that has the same metadata signature.
If you have loaded an assembly dynamically with Assembly.ReflectionOnlyLoad() then you can only do all the reflection operations against it (read the types, methods, properties, attributes, etc, but can not dynamically invoke any of them).
I am curious as to what your use case is for creating a metadata-only assembly. I've never had to do that before, and would love to know if you have found some interesting use for them...
If you are still interested in this possibility, I've made a fork of the il-repack project based on Mono.Cecil which accepts a "/meta" command line argument to generate a metadata only assembly for the public and protected types.
https://github.com/KarimLUCCIN/il-repack/tree/xna
(I tried it on the full XNA Framework and its working afaik ...)
Yes, this is new for .NET 4.0. I'm fairly sure this was done to avoid the nasty versioning problems in the .NET 2.0 service packs. Best example is the WaitHandle.WaitOne(int) overload, added and documented in SP2. A popular overload because it avoids having to guess at the proper value for *exitContext" in the WaitOne(int, bool) overload. Problem is, the program bombs when it is run on a version of 2.0 that's older than SP2. Not a happy diagnostic either. Isolating the reference assemblies ensures that this can't happen again.
I think those reference assemblies were created by starting from a copy of the compiled assemblies (like it was done in previous versions) and running them through a tool that strips the IL from the assembly. That tool is however not available to us, nothing in the bin/netfx 4.0 tools Windows 7.1 SDK subdirectory that could do this. Not exactly a tool that gets used often so it is probably not production quality :)
You might have luck with the Cecil Library (from Mono); I think the implementation allows ILMerge functionality, it might just as well write metadata only assemblies.
I have scanned the code base (documentation is sparse), but haven't found any obvious clues yet...
YYMV
Using VS2010 under windows 32 or 64 bit.
Our C# app calls a 3rd party DLL (managed) that interfaces to an unmanaged DLL.
The 3rd party DLL API appears identical in 32 or 64 bit although underneath it links to a 32 or 64 bit unmanaged DLL.
We want our C# app to run on either 32 or 64 bit OS, ideally it will auto detect the OS and load the appropriate 32rd party DLL - via a simple factory class which tests the Enviroment. So the neatest solution would be a runtime folder containing:
OurApp.exe 3rdParty32.DLL 3rdPartyUnmanaged32.DLL 3rdParty64.DLL 3rdPartyUnmanaged64.DLL
However, the interface for the managed 3rdParty 32 and 64 dll is identical so both cannot be referenced within the same VS2010 project: when adding the second the warning triangle is shown and it does not get referenced.
Is my only answer to create two extra library DLL projects to reference the 3rdParty 32 and 64 Dlls? So I would end up with this project arrangement:
Project 1: Builds OurApp.exe, dynamically creates an object for project2 or project3.
Project 2: Builds OurApp32.DLL which references 3rdParty32.dll
Project 3: Builds OurApp64.DLL which references 3rdParty64.dll
Since you have unmanaged code that is 32 bit or 64 bit specific, you lose the advantage of managed code being able to JIT into either mode at runtime. It might be simplest just to set up your make file to build your application twice, once for 64 bit and once for 32 bit, and use conditional sections in the csproj file to reference the 32 bit or 64 bit unmanaged DLLs. Let the installer install the binaries appropriate to the platform as found at install time.
I cant say I have done this before but a quick search tells me you can program against an interface and load the library dynamically via reflection.
Have you considered this?
Here's an idea, which should be possible by customizing your build process:
Have your project compile twice to YourApp32.exe and YourApp64.exe, modifying the references appropriately. Then also make a 3rd project with a bootstrapper YourApp.exe, which will only check the bit-ness of the system and load either YourApp32.exe or YourApp64.exe.
Naturally, this should probably be done only for release builds, because you effectively double your compile time, which will be annoying for the developers.
One option would be to use reflection in your factory to load the corrected 3rd party assembly at run time, and create an instance of the proper class, and return a reference to that. Then you can just put the assemblies in the same directory as your executable, and load the proper one at runtime, without adding a project reference. However, typically this uses either a known base abstract class or interface from another assembly (Typically one devoted to just holding the needed declarations). It does not sound like you have this.
However, depending on the complexity of the type hierarchy of the 3rd party managed DLL, there could be an option along this route, with slightly more work.
Create a set of classes in your own project that mirror the 3rd party dll's structure. Assuming the third party library isn't too complex, this will probably be just one class with many methods. You would also have to recreate any structures passed back and forth, if any.
Create a set of delegates that match the signatures of the methods to be called in the dll. For example, a method such as:string DoFoo(int a, int b) would have a delegate something like delegate string DoFooDelegate(int a, int b). If methods have the same signature, you can use a single delegate for all of those. Add to your set of classes created before a variable for each method to be called in the 3rd party DLL. So your classes would have a set of members along the lines of private DoFooDelegate doFoo;. Then can be whatever access level you deem appropriate.
For the most tedious part (Though you could probably do most of this with generic functions to assist). Using this http://msdn.microsoft.com/en-us/library/ms228976.aspx and this http://msdn.microsoft.com/en-us/library/74x8f551.aspx as a guide, create an instance of the wrapper classes, wire up each method from the 3rd party library to it's matching member in your classes. This should be done within your factory. Once done, return the new instance. You should then be able to call into the 3rd party assembly through your wrapper classes.
This is a very hacky way of doing this. If you have the option, get ahold of the 3rd party supplying the DLLs and see if you can convince them to expose either abstract classes or interfaces matching their two DLLs into a third assembly, then you can reference that, without all of the mucking around with delegates.
I am wondering how I would go about correctly setting up a C++/CLI library that wraps native c++ code that has several dependencies. I have tried both statically and dynamically linking the native library to its dependent libraries with no luck.
The Managed C++/CLI dll builds just fine and can be added as a reference to a C# project. However when I attempt to use any of the defined classes i receive either a BadImageFormatException or FileNotFoundException depending how i linked. I believe I need to specify the dependent libraries in the CLI library so it is loaded in the manifest but I am unsure of the process. Also because i know it will come up, I have verified that all of the libraries involved are built on the x86 architecture.
I figured out the problem and everything is working correctly now. It was a combination of several incorrect things all happening together.
If anyone has the same issue, I resolved it by setting up the following:
1) The Boost libraries that were referenced (specifically boost_thread) needed to be compiled with BOOST_THREAD_USE_DLL preprocessor (other boost libraries may need BOOST_ALL_DYN_LINK to just dynamically link everything). This is apparently a common issue.
2) I verified that all dependencies were in system Path (like R Ubben reiterated)
3) I used the DependencyWalker (depends.exe from sourceforge) to analyze my compiled managed DLL. It turned out that the libpq.lib library being used actually referenced additional DLLs that were not included in the lib folder but in the bin folder. So that need to be added to the Path.
4) Part of my wrapper was using the #include header for lists. This forced my library to link against 2.0 framework dependent libraries. This was not compatible with my 4.0 client targeted C# application. This was only made known by parsing through the Warnings from compiling (previously hidden due to C++ generating too many..foolish i know). However this was resulting in a System.BadImageFormateException being thrown despite everything targeting the same x86 architecture.
Hope that helps anyone else who has the same problem. The BadImageFormateException and FileNotFoundException were entirly too vague and unhelpful.
You should make the C++ dll in release mode and use extern "C" for public static things.
I have gotten that error when the dependent libraries were not in the path. The wrapper library is found because of the reference, but the reference does not also take care of the dependent libraries. Try placing them explicitly where the program is executing.