C++ DLL fails to load on some machines - c#

I'm trying to figure out the reason why my DLL fails to load on certain machines.
My application:
A C# program deployed with a setup.msi installer. Inside the installer are the DLLs that get placed in the install directory of the application. Ex:
OUTDIR = c:\Program Files\MyApplicationName\%OUTDIR%\MyApplication.exe
dir %OUTDIR%\DLL_FOLDER\\*.dll
myDLL.dll
The C# application calls LoadLibrary specified by:
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr LoadLibrary(string libname);
So basically
intPtr dll_handle = LoadLibrary("myDll.dll");
Is called and we use the dll_handle to call the desired functions.
So far this has worked on 5/7 of the machines I've deployed it on... What are the obvious mistakes I'm making here? :-)
Grateful for any help!

The most likely explanations are:
The DLL cannot be found. Since you don't specify a full path, you rely on the Dynamic-Link Library Search Order to locate it. Placing the DLL in the same directory as the executable is the usual way to make sure you can find it, and find the right version.
The DLL has non-matching bitness. For instance, your have a 64 bit process and a 32 bit DLL, or vice versa.
The DLL is found, and has the right bitness, but the DLL's dependencies cannot be resolved. Usually this means that the appropriate MSVC runtime needs to be installed on the target machine.
The first diagnostics step to take is to check the return value of LoadLibrary and if it is NULL then call GetLastError to retrieve an error code. In p/invoke you do that like so:
IntPtr lib = LoadLibrary(...);
if (lib == IntPtr.Zero)
throw new Win32Exception();
You can use a tool like Dependency Walker to debug the problem further.

Related

Logging which component is searching for which dll under which paths

An application that is trying to import unmanaged dlls via
[DllImport("Unmanaged.dll", EntryPoint = "UnmanagedMethod", ExactSpelling = true, CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
and
LoadLibrary("AnotherUnmanaged.dll" )
keeps throwing
HRESULT: 0x8007007E
exceptions.
The import works with absolute paths, i.e. the dlls exist and can be accessed. Since I can't use absolute paths in production, I need to find out which components need to know which additional include paths.
Is there a way to log all the info about which component is trying to find which dlls unter which paths?
The Exception itself should contain the filename of the dll that isn't found, can you try logging that after catching with try{}catch?
Otherwise you can try inspecting your own dll with a tool like Dependencywalker or similar wich can find relations in dll's.
Edit:
The search paths are the same for default windows search paths (since unmanaged dll's get loaded with a call to LoadLibrary in windows). These are amongst others:
Dll/exe directory
Current directory
Windows system folder: C:\windows\system32 or c:\windows\SysWOW64
Windows folder
The Path environment variable
More info about search paths: https://msdn.microsoft.com/en-us/ie/aa297182(v=vs.100)

Unable to import c++ dll to c# project using DllImport

I'm trying to import a C++ Project Dll into a C# project. I found a lot of people talk about using DllImport. I tried using that and here is what I have-
CPP Code:
int __declspec(dllexport) beginCode(double reportId);
C# Code:
[DllImport("C:\\Users\\<my_user_id>\\Desktop\\ctxmix\\Release\\ctxmix.dll",CallingConvention =CallingConvention.Cdecl ,CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = true)]
public static extern int beginCode(double reportId);
int result = beginCode(reportId);
But when I run, I'm getting an exception - Exception thrown:
System.DllNotFoundException
Do I have to add any references for the CPP Dll in the project or do anything else apart from the code which I have on the top?
Edit: I'm trying to run my .exe using VS2015 and I get this exception on my local machine. Also, I don't see my CPP Dll in the Project->References section where as I see other references there.
The unmanaged DLL needs to be locateable by your managed process. Typically that means placing the DLL in the same directory as the executable file. But you gave used an absolute path which I presume you transcribed correctly.
You may also encounter this error if the DLL's dependencies cannot be located. That seems the likely explanation here. Most likely the MSVC runtime cannot be located when your DLL is loaded.
Using an absolute path isn't a great idea. That will break down when you distribute to another machine. Use just the DLL file name and place it in the same directory as the executable.
Your DllImport attribute seems fussy. No point specifying CharSet when there is no text. I doubt your function calls SetLastError. And do you really need ExactSpelling?

loadlibrary fails with error code 127

I've a very interesting problem. It's sounds very easily, but I didn't finf any information about it.
I've a C# solution with excel Add-in and winforms application and library project with only one method.
project with library have next code:
[DllImport("Kernel32.dll", SetLastError = true, CharSet = CharSet.Ansi)]
public static extern IntPtr LoadLibrary(string filename);
public sealed class LibraryInfo
{
public readonly IntPtr Handle;
public LibraryInfo(string dllName)
{
Handle = LoadLibrary(dllName);
}
}
public LibraryInfo GetLib(string name)
{
return new LibraryInfo(name);
}
Look's like simple.
So I've a call of that method from add-ins and from WinForms
I've a Dll, builded for x64 platform and x86 platform.
And now magic:
LoadLibrary returns error code 127 only when I run it from Add-in and x64 configuration and on excel-2016(x64, ofcourse). When I run it on x86, or winform (both x86 and x64) it works. And it is not all, when I run it on Excel 2013 it's works fine too!!!
mayby somebody knows?
Error code 127 is ERROR_PROC_NOT_FOUND.
The specified procedure could not be found.
Typically that means that something is calling GetProcAddress which is failing because the module in question does not export a function of the specified name.
Exactly where that is happening cannot be discerned from the code that you supplied. Unfortunately you did not supply very much code, and did not supply the code that you are using. That much can be discerned from the fact that you mention an error code in spite of the code in your question performing no error checking.
It could be that code you did not show is calling GetProcAddress and failing. Or it could be that the loader is yielding that error code whilst resolving the dependencies of the library you load.
So, what I've stated above is a broad explanation for the behaviour that you report. Anything more specific would require the actual code in use, but only you have that code.
Problem solved.
I ve a dependent dll for my, called "Chart", so excel 2016 have "chart.dll", 2013 - not.
The solution is rename my "chart.dll" and rebuild both of dlls.

How to use a C++ dll in Unity3D?

I am aware of this similar question, but it does not respond to my problem.
I have written two .dlls using Visual Studio 2010. One is in C++, and communicates with an SDK that was written in C++. The other is a C# wrapper for that C++ library, so that it can be used in C# contexts.
My plan was that this would let me use my code in Unity3D, but apparently that is not the case. It seems like Unity3D does not allow me to import .dlls as Assets if they are not a .NET assembly. So I can add my C# wrapper, but not the C++ dll.
This results in a DllNotFoundException whenever I try to access the C++ library. I have tried simply copying the C++ library into the Assets/Plugins folder, but that gives the same results.
Is there a way to do this properly? This is a very vital part of my project setup.
The problem is that the DLL is not being found when the p/invoke runtime code calls LoadLibrary(YourNativeDllName).
You could resolve this by making sure that your DLL is on the DLL search path at the point where the first p/invoke call to it is made. For example by calling SetDllDirectory.
The solution that I personally prefer is for your managed code to p/invoke a call to LoadLibrary passing the full absolute path to the native DLL. That way when the subsequent p/invoke induced call to LoadLibrary(YourNativeDllName) is make, your native DLL is already in the process and so will be used.
internal static class NativeMethods
{
[DllImport("kernel32", SetLastError = true, CharSet = CharSet.Unicode)]
internal static extern IntPtr LoadLibrary(
string lpFileName
);
}
And then somewhere in your code:
private static IntPtr lib;
....
public static void LoadNativeDll(string FileName)
{
if (lib != IntPtr.Zero)
{
return;
}
lib = NativeMethods.LoadLibrary(FileName);
if (lib == IntPtr.Zero)
{
throw new Win32Exception();
}
}
Just make sure that you call LoadNativeDll passing the full path to the native library, before you call any of the p/invokes to that native library.
Note that the DllNotFoundException can be caused by building your Unity DLL in Debug instead of Release!
A simple oversight that can cause a headache.
This also happens when Unity can find your DLL, but is not able to find it's dependencies. Obvious fix is to place dependency DLLs into /Plugins as well, or link your dependencies statically.
Less obvious reason is when your DLL depends on Visual Studio runtime library dynamically, i.e. is built with Properties -> C/C++ -> Code Generation -> /MD option. Change it to /MT to link with runtime statically.

Unable to load Win32 Native DLL file from C#.NET

I have a C# winapp. I call a native .dll file (created in C++ by myself) from the C# app, and it works fine.
But when I copy my application (.exe and .dll files) to another machine, I get an error that says:
Unable to load DLL "c:\dllname.dll": The specified module could not be found. (Exception from HRESULT: 0x8007007E)
Here is the C# code:
class IsoMessageHelper
{
public const string ISO8583_DLL = "c:\\Hc8583.dll";
[DllImport(ISO8583_DLL, CallingConvention = CallingConvention.Cdecl)]
public static extern bool InitializationRq(...)
}
What should I do?
A common issue when deploying .Net applications that have native dependencies, is that the native dlls may be missing dependencies themselves on the target machines e.g. the correct version of the C runtime.
Use a tool such a Dependency Walker to analyze your native dll and determine if it has a missing dependency on the machine you have copied it too.
Try not to hard code any paths in the DllImport attribute parameter that specifies the name of the file. Then you should make usre the file is right besides the executable.
Something like this:
[DllImport("user32.dll", CharSet = CharSet.Unicode)]
Move the DLL to the root. If that works, then look at your attribute to determine why. You haven't posted any code, so I can't give you any specific reason.

Categories

Resources