If I reference an external unmanaged DLL in C# by the following:
[DLLImport("MyDLL.dll", ...
Where should the DLL be placed when I want to run the code from my IDE? Should it be in the bin\Debug folder?
Which compiling configuration you are using?
If you want to run the application from Visual Studio Debug/Run it would be in your project folder
If you want to run by double click, it should be near your exe which is in
bin\Debug
or
bin\Release
folder.
Anywhere locatable by the LoadLibrary function. See Dynamic-Link Library Search Order for more information:
If SafeDllSearchMode is enabled, the search order is as follows:
The directory from which the application loaded.
The system directory. Use the GetSystemDirectory function to get the path of this directory.
The 16-bit system directory. There is no function that obtains the path of this directory, but it is searched.
The Windows directory. Use the GetWindowsDirectory function to get the path of this directory.
The current directory.
The directories that are listed in the PATH environment variable. Note that this does not include the per-application path specified by the App Paths registry key. The App Paths key is not used when computing the DLL search path.
bin\Debug satisfies the first point, assuming that you're only ever running the application in its Debug configuration.
Yes, alongside the .exe file produced by the compiler (which ends up in bin\Debug\ as you said) should be perfect.
Related
I'm working on a SolidWorks plugin (DLL). It depends on a couple of files (sqlite DB, sketches etc). To install the plugin, you only have to open the DLL with SolidWorks.
In the DLL are some routines that call File.Open() on a number of resource files that I'll refer to by relative paths. The dir. hierarchy would look like:
Plugin/
plugin.dll
Sketches/
various.sldprt
otherfile.db
otherdeps.txt
...
Where the root dir. of the plugin can be anywhere on the system. The plugin can be easily loaded by SolidWorks with Open File Dialog. The problem is that once I load the DLL, any calls to File.Open() (eg File.Open("Sketches/various.sldprt")) with relative paths won't work because it'll be relative to the dir. where SLDWORKS.exe (SW install dir.) resides instead of the dir. of the DLL. This would mean I'll have to put all my resource files in the SolidWorks install dir., which I would like to avoid. Is that possible?
What you can do is add your addin folder as a prefix to any local path before calling File.Open().
Addin folder can be obtained as :
string path = System.IO.Path.GetDirectoryName(
System.Reflection.Assembly.GetExecutingAssembly().GetName().CodeBase );
Our C# / .NET program is calling a third party DLL (x.dll) in the target folder. x.dll is then calling another third party DLL y.dll in the same folder. At some systems, this does not work, because x.dll can't find y.dll.
The same program with the same dlls works on most other systems, but we can't find out what the differences are to the systems were it does not work. We checked the properties, the dlls are not blocked by Windows. Also the virus-scanner was disabled.
Please go through Dynamic-Link Library Search Order and see which case it applies. the most likely case is standard DLL search order with SafeDllSearchMode enabled:
If SafeDllSearchMode is enabled, the search order is as follows:
The directory from which the application loaded.
The system directory. Use the GetSystemDirectory function to get the path of this directory.
The 16-bit system directory. There is no function that obtains the path of this directory, but it is searched.
The Windows directory. Use the GetWindowsDirectory function to get the path of this directory.
The current directory.
The directories that are listed in the PATH environment variable. Note that this does not include the per-application path specified by
the App Paths registry key. The App Paths key is not used when
computing the DLL search path.
Note that if the DLL is a managed assembly (you do not mention it is) then the .Net assembly search rules apply, see How the Runtime Locates Assemblies. Obviously, GAC would also play a role for managed DLLs.
I'm just giving you the pointers to do your own investigations, since your post is missing the relevant info.
I am working on an application where users can develop their own plugins as dll files. They need to put these dll files to a specific path so my application(C++) can load them and run. The problem is, when user develops a dll file depends another dll file and put both files to my dll path, my application can't find second dll file.
Ex:
DllA(C++) depends DllB(C#)
my app loads DllA but can't find DllB and fails.
If user puts DllB into application binary path and DllA to specific dll path, I am able to execute plugin. I also tried to put DllB into various directories such as windows or system32 but it again fails. I also tried to add my dll path to PATH environment variable but no effect.
I am already executing SetDLLDirectory function to load DllA in the specific path. Since I've no control over user code, I can't make them to call this function in DllA code also. My question is that how can I force windows to search my specific dll path?
I have to use the C# class library code in my native code which is written in c++. For this I added one interface written in c++ add the my C# class library project as dependency to it. This works fine till I put the C# dll in .exe folder , but I put this in libs folders (where we keep our dll's), I get file not found exception when tried to call the C# dll function.
Is there any way to keep c# dll in libs folder and make it work?
Thanks.
Yes, you need to re-add it from the libs folder and it will be fine. Or if you are naming the DLL in your code itself, then just provide the full path along with the DLL name. Then when you recompile, the .exe will contain the path you gave it in the source code and will look for the DLL there.
From the MSDN(LoadLibrary),
Remarks section::
The first directory searched is the directory containing the image
file used to create the calling process (for more information, see the
CreateProcess function). Doing this allows private dynamic-link
library (DLL) files associated with a process to be found without
adding the process's installed directory to the PATH environment
variable. If a relative path is specified, the entire relative path is
appended to every token in the DLL search path list. To load a module
from a relative path without searching any other path, use
GetFullPathName to get a nonrelative path and call LoadLibrary with
the nonrelative path. For more information on the DLL search order,
see Dynamic-Link Library Search Order.
The search path can be altered
using the SetDllDirectory function. This solution is recommended
instead of using SetCurrentDirectory or hard-coding the full path to
the DLL.
If a path is specified and there is a redirection file for
the application, the function searches for the module in the
application's directory. If the module exists in the application's
directory, LoadLibrary ignores the specified path and loads the module
from the application's directory. If the module does not exist in the
application's directory, LoadLibrary loads the module from the
specified directory. For more information, see Dynamic Link Library
Redirection.
If you call LoadLibrary with the name of an assembly
without a path specification and the assembly is listed in the system
compatible manifest, the call is automatically redirected to the
side-by-side assembly.
This is all you need to know about path search of a dll. The easy solution, enter the full path in LoadLibrary call or set your PATH environment variable to contain the alternate path of the dll.
I am using a managed DLL that referencing an unmanaged dll.
I added the unmanaged dll under /External/foo/ directory, and i changed the "Copy To Output Directory" to always.
The problem is that the dlls are copied to the outputDir/External/foo dir and when the runtime tries to find it, it fails with this error: "Unable to load dll: Module cannot be found"
When i copy it directly to the output dir, everything works well.
How can i set the project runtime to search in the sub directories of the outut dir?
Thanks!
You don't want to do this, DLL Search Hell is something you want to avoid. Windows is pretty inflexible about where it looks for DLLs. Rightfully so, DLL Hell is nothing to mess with. The only good place for unmanaged DLLs is in the same directory as your EXE. If you don't want to store the DLLs in the project directory, so copying them is very easy, then you are going to need a post-build event that uses xcopy.exe to copy the DLL to the output directory.
The alternatives are not pretty. If this DLL is implicitly loaded then the only option is to use an installer to add the directory to the system's PATH environment variable. This is a Really Bad idea, way too easy for your program to break. If it is loaded explicitly, either with LoadLibrary or a pinvoke declaration then you have more attractive options since you can alter the search path in your Main() method before the DLL is needed. Either append the path to your local copy of the PATH environment variable by using Environment.SetEnvironmentVariable() or pinvoke SetDllDirectory(). Do beware that you have a deployment problem as well, somebody is going to have to create this subdirectory and copy the DLL there on the user's machine. All great reasons to not do this.
This is something we did in our last project. Write a batch file which copies this unmanaged dll to the output directory. Call the batch file every time the program compiles. You can control the calling of batch file also using a Config key. So it runs based on the config key value true/false. i hope this helps