Link dll from subfolders - c#

I have written a C++/CLI wrapper for some unamanaged dll's (OpenCV). Everything works fine until this point. Now I would like to store the dll's in a subfolder, so the final application structure would look like this:
bin\
MainApp.exe
wrapper.dll
Wrapper\library1.dll
Wrapper\library2.dll
Also, I would like to configure this in the Wrapper project, so I don't need to care about this in any other project using wrapper.dll
I have found several posts talking about this, but none of them seems to match my needs:
Setting the path in app.config file: wrapper.dll does not have an
app.config file, and I would have to add this reference in every
executable project using the dll.
Setting AppDomainSetup.PrivateBinPath: this could be a workaround, but I'm
not sure whether it works for unmanaged dll's.
Using ILMerge: Does it work for unmanaged dll's along with C++/CLI dll?
Ideally I am looking for a property in Project settings to add this subfolder, so every Solution including my project will look for the unmanaged dll's in the right folder.

The problem here is that the DLL's are usually loaded by Windows, and they're loaded when your application starts. Windows starts by looking at the EXE, finds what DLL's it needs, loads them, and then continues to load DLL's needed by DLL's. This is not specific to C++ or C#.
.Net does affect DLL loading, but that's not applicable to native DLL's.
So, what can you do? One solution is to not let Windows load your DLL's. Visual Studio has a DelayLoad option. This uses LoadLibrary at runtime. And with dliNotePreLoadLibrary you can control where it's loaded from. Since this happens at runtime from your DLL, the executables don't need to do anything.

Related

Loading C# DLL to C++/CLI - dependencies directory

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.

Mixed Assembly Not Discovering Native DLLs

I have a mixed mode dll with native dll dependencies.
I am loading the mixed mode dll from a C# exe using Assembly.Load. However, the location of the mixed mode dll is not in the application bin directory, therefore it fails because it only looks for the native C++ dll's in the bin and the folders in the PATH environment variable.
I thought using the option /assemblylinkresource was suppose to stop this and force the native dll's to be found in the alternate directory alongside the deployed mixed mode dll. This is proving to be not correct.
Is there a way to create a multi-file assembly with native dll's using an existing C++/CLI mixed mode dll? The only examples (http://msdn.microsoft.com/en-us/library/xawyf94k(v=vs.100).aspx) I've seen are using .netmodules coupled with a native dll.
Therefore, the solution is to either:
a) some how force the application to search for native dependencies in a directory of your choosing; or
b) package the native dll's into the one managed mixed mode assembly (is this even possible??) - given statically linking the dependencies is not an option.
Normal Windows DLL searching rules apply. So yes, there's no hope it will ever find those DLLs. A "multi-file assembly" isn't going to work either, you cannot merge native code. Options you have, roughly in preferred order:
Call SetDllDirectory() to add the path that contains the DLLs to the set of directories where Windows will look. May fail if the external code uses it as well.
Use Environment.SetEnvironmentVariable() to append the path to the PATH environment variable. This only changes the process' copy of the PATH so is a reasonable approach. May fail on machines that have a bloated PATH that is reaching the limit.
Set Enviroment.CurrentDirectory to the path with the DLLs. May fail if the external code tinkers with it as well.
Record the path for each DLL at install time in the HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\KnownDLLs registry key.
Install the DLLs in the Windows side-by-side cache and use a manifest to tell Windows about it. This is hard to get right.
Potential candidate for a solution, not tested with MMA: This is probably not the optimal solution you were hoping for, but I thought I would add it as it could help you along the way to achieve solution a). In c++ you could control loading path and path search order by either manually setting the directory to be searched using SetDllDirectory (only available from XP SP1) or by manually loading the dll using LoadLibraryEx.
I guess one could use P/invokes to get access to these calls in C#
[DllImport("kernel32.dll", CharSet=CharSet.Auto)]
private static extern void SetDllDirectory(string lpPathName);

Referenced DLL Cannot Be Found When Running Application

I have a weird situation with some code that I inherited at work. Their application is a multi-project solution, with several of the solutions being (code) pieces of the MS Enterprise Library (not sure which version).
They also have an existing C++ (unmanaged) application which has a bunch of DLLs. One of these DLLs is built in a separate solution, both in 64-bit and 32-bit flavours.
The main application has a reference to this DLL, and calls a couple of static functions (I can see intellisense, even). I can compile and build the main application EXEs, but when I run it, I get an exception that this DLL from the unmanaged code (lets call it CPlusPlusCode.dll cannot be found:
FileNotFound Exception was unhandled: Could not load file or assembly 'CPlusPlusCode.dll' or one of its dependencies. The specified module could not be found.
I'm quite stumped, because I can compile the code, see intellisense for the imported classes, and dig into the DLL in the object browser. I even made sure there's a copy in the \bin\Debug folder (although I don't see why that would make a difference). This is for a Windows Forms application.
Also, if it matters, I had some build issues related to x86 vs. x64 for different projects; I think (hope?) that this is not related to that, but I solved that by using the Configuration Manager to build everything as x64.
Check the GAC, and if necessary you might need to add it or register the DLL there.
I had this problem with a project, it all works ok from Visual Studio and most of my times running the project locally on my machine. But because of the unmanaged code I needed specifically allow the project to be executed with correct permission levels.
So have a look in the manifest file, that enough permissions etc exist.

DllNotFoundException for .dll which is in current folder

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.

Where to put my dll files using F#

I have a library with both managed and unmanaged C#, C++ dll files. I want to reference it from F#. Where can I place the C#, C++ dll files? I can not place them in the application folder (I must have copy local = false) and it will be only me who will use the program. I have tried windows/system32, GAC using setup and adding PATH variable pointing to a folder with all the dll files but none of it seems to work.
Thanks for any hint
When building your application in Visual Studio, it looks for the references in all the default folders (depending on your OS, .NET Framework version and other things) but also in locations you specified in the project configuration. Right click on the project in Solution Explorer, click Properties and go to the Reference Paths tab. Add C:\MyDllFolder or anything.
If you do this in all your applications which are using that dll, you could just have it sitting there once.
You can specify dll locations MSDN : Specifying an Assembly's Location or maybe use something like
Assembly.LoadFrom
if you want dynamics.

Categories