Blazor project can't find native dll dependencies - c#

I have a Blazor server x86 project that requires a 32-bit native DLL (native.dll). In a class wrapper I use DllImport as follows:
[DllImport("native.dll")]
internal static extern int Method1();
[DllImport("Native.dll, CharSet=CharSet.Unicode")]
internal static extern int Method2(string countryName, string abbreviation, int i);
In a Razor component, I load the DLL as follows (the DLL is marked "Copy to output always"):
IntPtr ptr = NativeLibrary.Load("native.dll");
The DLL loads fine and the first call to Method1 works great. But when I call Method2, I get a DLLNotFoundException (Unable to load DLL 'native.dll, CharSet=CharSet.Unicode' or one of its dependencies). Using DumpBin I determined that the native.dll has three dependencies: kernel32.dll, user32.dll and advapi32.dll. These, of course, have their own dependencies.
I have tried adding Windows\SysWOW64 to the PATH, but no help, and should not have to do that anyway.
How do I tell the app to include, or find, the native dependencies?

Related

LoadLibrary() returns 0 in C#

I am creating an Autodesk Revit add-in in C#. Output of this project is a DLL itself. Within this project, I am loading another unmanaged DLL by calling:
IntPtr pDll = LoadLibrary("E:\\Rep3DLib\\builds\\Release\\Index.dll");
int a = Marshal.GetLastWin32Error();
Within debugger, I see that pDll has value 0 and a has value 127 (Error: The specified procedure could not be found.). This is surprising because I am not even looking any particular procedure within the DLL. I just want to load the DLL.
Now I delete the unmanaged DLL from E:\\Rep3DLib\\builds\\Release\\Index.dll and in the above code, a has value 126 (Error: The specified module could not be found.). This does make sense. It also means that when the DLL is present at the correct location, the code is able to find it but somehow it's looking for a procedure which it's not able to find.
To debug this problem, I created another project within the same solution. Here's the code for this project:
namespace testIndex {
class Program {
[DllImport("kernel32.dll", SetLastError = true)]
public static extern IntPtr LoadLibrary(string dllToLoad);
static void Main(string[] args) {
IntPtr pDll = LoadLibrary("E:\\Rep3DLib\\builds\\Release\\Index.dll");
int a = Marshal.GetLastWin32Error();
}
}
}
When I run this, pDll has a non-zero value and I am able to call the functions defined within the Index.dll.
Note that both the projects have target platform as x64. I also verified that if I build the Revit add-in and run it on a different machine, it does find the DLL. So somehow it's not finding the DLL only on my machine although the path E:\\Rep3DLib\\builds\\Release\\Index.dll is definitely correct.
Any idea what could be wrong?
Here's the answer to the question I posted above. My add-in was using a dependent DLL named "pcl_features_release.dll". Revit was loading another add-in before mine, which was also loading its own "pcl_features_release.dll" which might be slightly different than mine. As a result, although Revit was finding my DLL, it was not able to load it.
Another question: In this case, two add-ins are dependent on "pcl_features_release.dll", which is a DLL supplied by Point Cloud Library (http://pointclouds.org/). What is the best practice to avoid conflict in such cases. I can not change someone else's add-in. How do I make sure that my add-in loads my "pcl_features_release.dll" that is being supplied with the add-in?

Why can't my C# application load my C++ dll?

I want to use C++ code in a C# application, so I wrote a DLL in C++.
Because it's the first time that I create a C++ DLL, I started by creating a 'test' dll. Here's the code
extern "C"
{
__declspec(dllexport) void DisplayHelloFromDLL()
{
printf("Hello from DLL !\n");
}
}
Than I made a very simple C# application:
class DllTest {
[DllImport("Test.dll")]
public static extern void DisplayHelloFromDLL();
public static void UseDll() {
DisplayHelloFromDLL();
}
}
After, I built both applications and moved the executable and the dll in the same folder. But when I ran the executable, it showed the following message:
Unhandled exception: System.DllNotFoundException: Unable to load DLL 'Test.dll': The specified module could not be found
you need to store the DLL in debug folder.
and try this command to check that method is exported properly
dumpbin /exports Test.dll
you have to check the target platform of both dll and exe.
Edit: When Target are different the exception is BadImageFormatException
You will have the DllNotFoundException when the dll or one of its dependencies is not found.
For example, when you compile a debug version of the DLL with VisualStudio, it needs the debug runtimes (which are not installed on machine without the IDE).
you can check your dll dependencies using the Dependency Walker
This tools will also helps you to see the targetted system (x86/x64) and the exported functions (use it on the dll, the program will not show you the [DllImport] dependencies)

c# calling LoadLibrary from a 64-bit process to load a 64-bit library fails

I'm having a problem on a machine while attempting at loading a library with a P/Invoke call to LoadLibrary.
[DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Auto)]
public static extern IntPtr LoadLibrary(string dllToLoad);
This is my configuration. The calling assembly (A) is compiled in x64 and it calls another assembly (B) compiled as AnyCPU. From B I call LoadLibrary(dll_C_Path) to a library C that is 64-bit. All this works on my machine running Win10 64-bit, but it fails on another machine running Win7 64-bit with the following error (after calling GetLastError): "%1 is not a valid Win32 application".
On B, before calling LoadLibrary I've verified that Environment.Is64BitProcess=true. I've opened the library C with DependencyWalker and it appears 64-bit. But the most strange thing to me is that on one machine works while on another not. What can be the cause?
EDIT
I'm passing the full absolute path to LoadLibrary. Here below a screenshort from Depency Walker (library C is aec.dll). I'm not used to it, but one thing I noticed is that the msvcr120.dll, which aec.dll depends on, has not the icon of a 64-bit. Can this give some hint?
There are two possible explanations:
Your code finds a 32 bit DLL, or an otherwise invalid image. We don't know whether you rely of the DLL search path or specify an absolute path.
Your code finds a 64 bit DLL but when it resolves its dependencies, a 32 bit or otherwise invalid module is found.
You should do some debugging to work out what is wrong. I would write a simple C++ program to load the library and avoid the extra complexity of p/invoke. I'd use Dependency Viewer in profile mode to determine which dependency is not valid.

Native DLL Not found

I have a program that uses Tesseract to extract text from images. I made a Native C++ DLL that is used in C# via P/Invoke. My C# application is a console x64 based and the DLL is also 64 bit.
After deploying to a Windows Server I receive an error that suggets the DLL (one I've made) does not exists. The error message is below.
System.DllNotFoundException: Unable to load DLL 'TesseractX64.dll': The specified module could not be found. (Exception from HRESULT: 0x8007007E) at Utilities.Finance.PDFParser.PDF.OCRObject.GetUTF8Text(String path, String lang, String imgPath)
I know for sure that the DLL exists in that path. The TesseractX64.DLL is placed in the same folder as the C# application so it should work without any issues.
Here is my code:
[HandleProcessCorruptedStateExceptions]
[DllImport(#"TesseractX64.dll", EntryPoint = "GetUTF8Text", CallingConvention = CallingConvention.Cdecl)]
private static extern IntPtr GetUTF8Text(string path, string lang, string imgPath);
What I have tried so far:
Set the DLLImport path to a relative path for example C:\DLL\Tesseract.DLL. Still same issue.
Installed Visual C++ 2005 - 2012 both x86 and x64. Still same issue.
It works perfectly fine on my Windows 7 x64 computer that I used to develop the program.
Either:
The DLL cannot be found, or
One of the DLL's dependencies cannot be found.
Place the DLL in the same directory as the executable to ensure that it can be found.
Make sure that all the DLL's dependencies are met on each machine that needs to run your software. That will involve first working out what those dependencies are. The documentation for the DLL should tell you that information. Typically this means installing the MSVC runtime against which the DLL was linked.
You aren't allowed to redistribute the debug runtime. You'll want to make a release build of the native DLL even if the .NET code is in debug mode.

Call unmanaged C++ VS 6.0 MFC dll from C#

I have an unmanaged C++ MFC dll that was developed in VS 6.0. I would like to use it in my C# app. I'm trying to use PInvoke.
Here is the C++ code:
// testDll.cpp : Defines the entry point for the DLL application.
//
#include "stdafx.h"
extern "C" {
BOOL APIENTRY DllMain( HANDLE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
return TRUE;
}
__declspec(dllexport) int test(int a)
{
return a * a;
}
}
And here is how I'm trying to invoke the method "test" from C#:
// PInvokeTest.cs
using System;
using System.Runtime.InteropServices;
class PlatformInvokeTest
{
[DllImport("TestDll.dll")]
internal static extern int test(int number);
public static void Main()
{
Console.WriteLine(test(5));
}
}
This approach works just fine when I set C++ dll to be just a regular Win32 dll.
But once I change the project type to MFC ("Use MFC in a Shared DLL") I'm getting this error:
Unhandled Exception: System.DllNotFoundException: Unable to load DLL 'TestDll.dll': The specified module could not be found. (Exception from HRESULT: 0x8007007E)
at PlatformInvokeTest.test(Int32 number)
Thanks!
TestDll.dll probably can't load one of it's dependent DLL's.
Try loading your TestDll.dll file in the Depends (Dependency Walker) utility. Depends should be installed with VC 6, under Microsoft Visual Studio 6.0 Tools. That will show you what dependencies the DLL has and will flag if one of the dependencies failed.
Make sure you load the TestDll.dll from the same folder that the C# code does.
Note that Depends only works with unmanaged DLL's.
The DLL needs to be in a path where the system can pick it up. have you put it in the directory where your application starts ? (probably in a DEBUG folder of you VS solution).
The second option is to give it the absolute path of the DLL.
The third option is to place it in "c:\windows\System" but this is a '-1' approach :D
In general, when you hit errors like this you can use Assembly Binding Log Viewer to determine if the dll is failing to load because of a missing dependency.
In your particular case, the most probabl cause is that you are dynamically linking your dll to MFC and when the C# app attempts to load your dll, it is failing to load the MFC dlls.
You can either copy the required MFC dlls side-by-side or you can switch to statically linking MFC to your lib.

Categories