I have a question concerning a COM C# component being created from a native C++ application.
The C# component is referencing an assembly which contains the COM interface.
So project A(.dll) contains the COM interface, project B(.dll) contains the COM class that implements this interface.
This C# COM component is then registered using regasm from some folder on my system, say for example:
C:\TestComponent which contains A.dll & B.dll, B being the one registered using regasm.
When my native C++ application (COM server), which is installed in another path, is trying to create an instance of the C# COM class from project B this fails complaining that A.dll can not be found.
If I copy (only) A.dll to the installation directory of my native C++ app, everything works perfectly.
Any ideas on how to tell my native C++ app that it needs to find the A.dll in a specified directory or in the directory where B.dll resides?
Kind regards,
Dwight
Having dependencies in a COM server is always a problem, whether it is an unmanaged server or one written in C#. Just like Windows, the CLR will only look in a few select places for a DLL. Which are the GAC and the directory where the EXE resides. With an option to also look in subdirectories of the EXE directory by using a app.exe.config file.
Knocking off the candidates here: you'll want to avoid giving the client EXE a .config file, you don't control its location nor configuration, it is somebody else's program. Same problem with the EXE directory.
Which leaves the GAC.
Also the location that Regasm.exe prefers, just omit the /codebase option when you register after you put the assemblies in the GAC. And a very good way to solve the DLL Hell problem that's so strongly associated with COM, the GAC can store different versions of your DLLs.
As far as I understand, you only registered B.dll. That is the reason, the COM System has no knowledge, where A.dll reside. I do not know a way to tell the application where it can found a, except of changing the workingdirectory or add the path to the A.dll to the system path variable or last but not least copy the A.dll into the system32 directory (but I hate that).
By the way, having a DLL proxy, like A.dll is, reside in the same directory as your application seems totally fine to me.
Ah one more thing. You can, if you now the path of the A.dll but did not want any of the above solutions, you can have a look into Loadlibrary.
Related
I have project with managed DLL A.dll which depends on managed B.dll and C.dll.
I expose A.DLL to unmanaged C++ project D via COM interface. Everything is okay... But A.DLL can't find D.dll and C.dll and raises appropriate exception. I tried putting them in the same folder but it does not work. How and where should I reference those dependencies?
In C++ I would just build A.dll with static linking but .NET does not have this option.
Update: putting library in the same directory as .exe file works, I just lost my binary.
Normal CLR search rules apply here. It first looks in the GAC and next looks in the directory in which the EXE is located. You can convince the COM runtime to locate A.dll from the registration, it can be stored anywhere the Regasm.exe /codebase option tells it to look. But that does not affect where the CLR looks for dependencies, it only considers the EXE location.
You can troubleshoot this by using the Fuslogvw.exe utility.
Alternatives are in general troublesome. As long as you have a [ComVisible] type in A.dll that's guaranteed to be instantiated first (think "Application") then you can subscribe the AppDomain.CurrentDomain.AssemblyResolve event in the constructor to help the CLR locate the other DLLs. But it is very important the constructor doesn't need types from B or C, you'll still crash when the jitter needs them to compile the constructor.
If that's not a suitable option then writing an appname.exe.config file can be somewhat useful if you prefer deploying the DLLs in a subdirectory of the EXE install directory. This is however rarely a good idea in a COM scenario since you are typically not in control over the EXE, it is usually somebody else's responsibility. Deploying locally is fine when you test your code. For production deployment you ought to seriously consider the GAC. In general a good idea in COM anyway since registration is machine-global which gives it strong DLL Hell headaches.
I'm developing an application that depends on some 3rd party dll's (it's actually a plugin to the 3rd party application, and I receive COM objects implementing certain interfaces declared in those dll's). My project contains references to those dll's locally exist on the dev machine, but I want to avoid wraping them inside my installer (for size and legal considerations).
Instead, my installer requires that the dll's are already existing on the target machine, and their path is saved to a text file next to my executable assembly.
How can I use this file to link to the dll's on run time?
Or is it better to add an environment variable during installation and use it instead (how can it be done)?
Using project references, I do not know of a way to have dlls in an arbitrary location. Typically I've handled this issue using an installer, like InstallAware, prompted the user for the 3rd party location, and copied the dlls into my projects folder at the same relative location I chose in my solution file.
If this is improbable for you, you can always load the dlls and create instances of the classes yourself by hand using Assembly.LoadFrom and Activator.CreateInstance.
I hope this helps.
I wrote a dll c++/cli library which uses my other c# dll library. C++/cli library works fine when I've got c# dll in the same folder as application which calls it. This library will be finally loaded to many applications and a C# dll must not be copied into directory with application. It has to be in the same folder as c++/cli library, but in that cases I've got System.IO.FileNotFoundException.
My suggestion is to load c# library manually or to change path where f.ex. firefox is looking for dependencies, but I tried with LoadLibrary() and Assembly::LoadFrom() methods to force loading from right directory. Of course I added directory path with dll to system PATH.
I work on VS2010.
You don't change the default directory where an application will look for dlls.
At design time put your dll in some well know location, the one you are going to deploy to. Add a reference to it, make sure it's set to Don't copy ever, otherwise it will end up in the bin folder. You have to do this otherwise it won't compile.
When you deploy, you'll need one package to deploy common dlls, and one for each application. Careful you don't create your own version of dll hell, if appA needs an older or new version of the common dll, compared to AppB
Add an AppDomain.AssemblyResolve event to main (for windows app). At run time the event handler will get fired when you reference a type in your dll, and the assembly has not yet been loaded.
In there you load it from the well known location. That usually in config, or in a relative path.
E.g.
AllMyApps
CommonDLLS
MyFirstApp
So the path you load the required common dll from would be "..\CommonDlls\MyCommondll.dll".
NB you will want to secure the dlls in some way, otherwise a bad guy might be able to inject their version of one in to your app, which would be bad...
You can use this mechanism to get the dll from a remote server or a database blob as well.
The simplest case is only a few lines of code, just look the event up. Took me about 15 minutes to get this going in a similar scenario.
Not on this machine though, otherwise I'd have pasted in the code.
I make use of the Belgium Identity Card SDK for reading data from a idcard.
The SDK exists of 2 components: interface dll and a wrapper dll.
In VS2010, i can make a reference to the interface dll, but not to the wrapper dll, so I put it manually in the bin folder. When I migrate my application to another pc on the localhost, it is not able to find the wrapper dll.
Not even when I (on the 2nd pc):
-installed the sdk.
-put the wrapper dll into the bin folder and system32 folder
In visual studio, properties of the interface dll, I've set "Copy Local" to true.
What can I do?
This could just be a difference in path names between machines.
I would create a folder at the top level of your solution and place these DLLs in there. Call it something obvious like "Solution dependencies". Then you can reference them as needed and set them copy to local as required. You wont always be able to reference a DLL, especially if it isn't .NET compatible.
I'm curious about your statement of interface and wrapper dlls. Is the wrapper dll not meant to be a .NET wrapper for a C++ style dll?
I'm getting a System.DllNotFoundException for a .dll which is in the same folder as the executable whenever my application attempts to use a function which exists in the DLL. The weird thing is that it is only occurring on one user's PC; it works fine on my dev PC and it works fine on one non-dev PC that I tried it on. Also, there are other DLLs in the folder which are being found and used correctly. The DLL in question is a native library which is referenced by my application via another DLL which is a c# wrapper for the native library.
My initial instinct is that there must be some other library being referenced by this DLL which doesn't exist on the problematic PC, but I cannot imagine what library this PC could be missing that the other non-dev PC has.
So my questions are this: is there a way to determine the dependencies of a given DLL file? Keep in mind that the DLL in question is a native library (i.e. not managed code), and I do not have access to it's source code. And if it turns out no dependency is missing, what else might cause such an issue?
For unmanaged dlls you can use Dependency Walker to find dependencies.
I would suggest using ILSpy to open the dll and view its dependencies first.