dll not found (non COM object) - c#

I made an application in vs2010 (.net 4.0). I published it, both using publisher and InstallShield LE.
But when I run application, I get error that a dll is not found. I know which dll is missing. This is a non-COM object and I can't add it to my project in vs2010. I am using a wrapper library which invokes this dll.
If I paste that dll in syswow64, my application works fine. But I want a cleaner way of doing it. I already had a look at Hans's answer here. But I have no clue what is side-by-side cache.
Adding path to environment variables works fine too.
I am not sure if updating registry and adding a path value will work or not. I would like to know if I can update registry for my application and direct the path where it searches for particular dlls.
Thanks.

Modifying the user's PATH variable is a very heavyweight solution, and you should avoid that. Likewise, do not put the DLL in the system directory. That belongs to the system and is private to you.
The recommended way to solve the problem is simply to put the DLL in the same directory as the executable. The directory in which the executable lives is searched first when the loaded tries to locate DLLs. It is the safest place to put your native DLLs.
If for some reason you cannot put the DLL in the executable directory, there are other options:
Call SetDllDirectory with the directory of your DLL before making your first p/invoke call. When that call returns, call SetDllDirectory passing NULL to restore the default DLL search order.
Make an explicit call to LoadLibrary with the full path of your DLL before making your first p/invoke call. Once the DLL has been loaded, future p/invoke calls will use the module that has been loaded.

If you know the DLL name in advance, there is a simple way.
You can simply use LoadLibrary to load the DLL from its known location (based on for example a configuration file entry).
As long as you successfully call LoadLibrary before any of the DLL methods are used, this will succeed as the DLL is already loaded.
This works because you can LoadLibrary with a full path, and once that is done, subsequent calls to LoadLibrary with just the filename will succeed immediately, since the library is already loaded.

Related

.NET cannot locate unmanaged DLL in same directory

I have a C++ DLL library (let's call it unmanaged.dll) that gets wrapped around a managed .NET library (let's call it managed.dll). The managed.dll uses unmanaged.lib to import/link unmanaged.dll. I have another ASP.NET Web API project that uses managed.dll (let's call the project webapi.dll). Now, whenever I build the Web project, in the output directory I get webapi.dll and managed.dll. Then, I manually copy unmanaged.dll to be in the same output folder so that (presumably) .NET can locate it and load it.
However, when I try to run webapi.dll, it fails with an error that it cannot load managed.dll:
Could not load file or assembly 'managed.DLL' or one of its dependencies. The specified module could not be found.
This is particularly weird because unmanaged.dll is in the same folder.
What I find very weird is that if I put unmanaged.dll under C:\Windows\system32 then .NET can properly load it!
My question is how can I make this unmanaged.dll visible to .NET in the folder where the .NET project output is residing?
It's the IIS that is causing the problems. Had the same problem, sovled it by adding the dll to a folder, that lies in the PATH variable.

c# Use dll with different versions in one directory

How can I use different dll's (other Version) with the same name in one directory?
For Example, LibA (ExternalLib.dll) has Version 1 and LibB (ExternalLib.dll) has Version 2.
I'm deploying all my programs to the same directory (this is our companys standard and I can't change this fact). The problem is if ProgramB which is using the LibB is deployed in the directory where ProgramA is using the LibA then ProgrammA would not longer work.
For my own Libs I use a Major-Version-Number (.01, .02) if there are big changes. But the Lib I'm using is an external Lib and each version of it requires different licensing-keys (which are handled by the programs itself).
I tried to rename the external libs from "ExternalLib.dll" to "ExternalLib.v1.dll" and "ExternalLib.v2.dll", but when I run my fresh compiled programm it throws an exception that says "ExternalLib.dll could not be found". The reference in my project is set to "ExternalLib.v1.dll" and compilation works fine.
Any ideas / suggestions to handle different assembly versions in the same directory?
Unfortunately, the filename of the DLL file has very little do do with how .Net is loading these types. The actual name is written into the meta data of the assembly as part of the compilation process. So at runtime, it will be probing for ExternalLib.dll regardless of what you renamed the file to. The usual way to fix this is to install to the GAC and use Strong Naming to reference the specific version.
Given you may not be able to do this, there are 4 things you could try:
Ask the vendor to produce version specific DLL's for you. They could compile such that the version name is part of the filename and included in the assembly manifest. This would be the simplest solution for you.
Handle the AssemblyResolve event and manually try and use Assembly.Load to point at the file you want such that you can specify specifically which dll to use. See http://support.microsoft.com/kb/837908 for more information, but effectively you'll be using Assembly.LoadFrom(specific_path) to choose the file where the code will load from.
If possible, you might also be able to use ildasm.exe to decompile the dll's to Intermediate Language (IL), then use ilasm.exe to recompile it to a new dll name. You would then reference this new DLL name in your project.
If the assembly is not signed, then you may be able to edit the manifest yourself; you can either use a compatible binary editor or possibly MT.exe.

windows service Can't call C++ Native Methods [DllImpor("myDLL")]

I tried to use this way:
DLLImport a variable MFC dll
It works.
The problem is the C++ dll "myDLL" needs another DLL "XDLL",
I found that
the service current fodler when services started is the system32, not where the assemble are !!!
In this case, if I put "XDLL" in system32 it would work...
What I need is away to run it without copying anything to System32 or anyway else
Is it C# windows service issue ? or C++ ? what should I do ?
Thanks
If DLLs are specified by name only, that is without a complete path, then the Dynamic-Link Library Search Order comes into play.
There are lots of ifs and buts with this, but the bottom line is that if you put all the DLLs that your executable needs in the same directory as the executable, then the loader will be able to find the DLLs. That is the best practice because it requires no configuration, and you can be certain of which version of the DLL is to be loaded.

iis7 hosted wcf service : avoid placing dll in system32 folder

I have a wcf service referencing a dll. Only way it works is by placing the dll in %windir%/system32 folder.
Things I have tried
tried switching between iis express, development server and iis (but this is irrelevant)
placing the dll in the bin folder and/or other application folders
trying to use the "regsvr32" util but the dll is not a com dll so it does not work.(no ddl entry point)
It is not a .NET dll so I don't think GAC can be manipulated to work with this
played with the system path variable without any success
What I actually want
A simpler method to access the dlls so I do not have to place the dll in system32 but contain it in an application folder and access it from there.
What am I missing?
EDIT:
I did find this post interesting and similar but again, it also uses the system32 method which is not the way to go.
If this is a win32 native library, you can "preload" it from a known location using pinvoked LoadLibrary passing a full path of your library as a parameter, somewhere early in your processing pipeline.
When any method from the library decorated with DllImport is called, the runtime will try to load the library (and would fall because the dll cannot be found) but since you preloaded it eariler, loading will succeed (loader checks the library file name, doesn't pay any attention to the directory the library is loaded from).

C++ calling managed COM object can't find dependent assemblies

I've created and registered a managed COM library in C# on my development machine. I've successfully registered it and created a .tlb file with regasm, and successfully imported the tlb into a c++ console app used for testing.
My COM assembly is called "efcAPI.dll" and it references another assembly that has not been set up for COM or registered in anyway called "efcServerDiscovery.dll". This second dll contains some code used by my COM dll and exists in the same folder as efcAPI.dll.
Everything concerning loading the COM assembly works fine. I can create instances of my classes defined in the COM and call methods from them. However when I call certain methods that use the code defined in efcServerDiscovery.dll I get a _com_error which reports that it could not load file or assembly 'efcServerDiscovery'.
I've verified that everywhere on my hard drive where efcAPI.dll exists there's a copy of efcServerDiscovery.dll (which is just the location I built and registered efcAPI.dll from). I've also attempted to place efcAPI.dll and efcServerDiscovery.dll in the same directory as the c++ app with no success.
Any suggestions as to where the c++ app is looking for the assembly or how to discover where it's looking would be great!
Yes, this is a problem with COM components having non-COM dependencies. Windows doesn't consider the location of the COM DLL when it searches for dependent DLLs. The normal search rules are in effect, the folder that contains the EXE first, Windows directories, current working directory, PATH environment. The location of the COM server does not play a role.
Assuming you don't want to deploy to the EXE folder, none of these are good places to store your DLL, although plenty of installers made the desperation move of storing it in c:\windows\system32 or modify the system PATH environment variable.
One thing you could do is P/Invoke SetDllDirectory() in your C# code before running any code in the DLL. Using Assembly.GetExecutingAssembly().Location will do it. That is however not a safe thing to do though, it might alter the search rules for the app that uses your component.
The only real fix is to install the DLL in the Windows side-by-side cache (WinSxS) and to include a manifest in your C# executable. Given the state of the documentation, I can only wish you the best of luck.
In these situations i always start with Dependency Walker verifying that what & where its trying to load is what i think it is.
fuslogvw will tell you where the CLR is looking for assemblies
Or use GAC.
(here are your characters, stackoverflow)

Categories

Resources