I'm trying to use crypto++ in c++ clr class library.
The problem is that I get an error as I run the app, but it builds successfully.
Unhandled Exception: System.IO.FileLoadException: Could not load file or assembly 'auth.dll' or one of its dependencies. A dynamic link library (DLL) initialization routine failed. (Exception from HRESULT: 0x8007045A)
at ConsoleApp52.Program.Main(String[] args)
This error only occurs when I include anything from crypto++
#include "dll.h"
#include "sha.h"
#include "filters.h"
#include "hex.h"
If I remove the following lines, it works.
I've tried copying the cryptopp.dll to the bin/x64/Debug and bin/Debug, but it did not resolve the issue.
What else do I need to include? Am I Missing something?
Dependecies:
Error code 0x8007045A most often means 32/64 bit DLL incompatibility.
If you're using native DLLs with managed code, make sure to use 64-bit versions on a 64-bit OS.
Related
I've looked over a few questions with a title just like this one, but they either do not talk about command line, or don't seem to work for me for some reason. From what I have read, it seemed as if I could "simply" do the following:
The dummy code (C#):
using System;
public static class Foo {
public static void Bar() {
Console.WriteLine("o3o");
}
}
More dummy code (Visual C++):
#using <test.dll>
int main() {
Foo::Bar();
return 0;
}
C# DLL compiled using:
csc /out:test.dll /t:library src\cs\Foo.cs
Visual C++ object file compiled using:
cl /Ox /clr /AI. /c src\vc\test.cpp
Executable compiled using:
link /out:test.exe test.obj
The following exception is thrown upon running the executable:
Unhandled Exception: System.TypeLoadException: Could not load type 'Foo' from assembly 'test, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null'.
at main()
at mainCRTStartup()
I have a strong feeling that I was supposed to also reference the DLL in the link phase, but I couldn't find any option for linking a DLL similar to GCC's -l option. Attempting to pass the DLL along with the .obj to link causes it to tell me that linking assemblies is not supported. Interestingly, though, if I build a .netmodule instead of a DLL, i.e. by:
csc /out:test.dll /t:module src\cs\Foo.cs
and changing the #using directive to
#using <test.netmodule>
the executable runs without error. This feels a bit weird, for I don't think anybody packages code in .netmodules (what are .netmodules, anyway?).
All of your steps should have worked, but one very simple issue is preventing your program from running.
Namely: Your C# DLL assembly name is test, and your C++/CLI exe assembly has the same name. They both have the same identity.
So when looking for Foo::Bar in the test assembly, the loader first checks if the assembly is loaded in the AppDomain. It is - it's your C++/CLI exe, and you can't have several assemblies with the same identity loaded simultaneously within the same AppDomain. Your C# dll wasn't even given a try.
Just change either one of them and everything will work fine:
link /out:test2.exe test.obj
As for what's a .netmodule, it's the format used for linking managed code statically, that's why you managed to link your C# code with your C++/CLI code without issues. It's roughly the equivalent of a .lib file for managed code.
And you're right, it's not used very often.
I am using C# loading C++ dll, and got this error:
"An unhandled exception of type 'System.BadImageFormatException' occurred in MyApp.exe"
"Additional information: An attempt was made to load a program with an incorrect format. (Exception from HRESULT: 0x8057000B)
I could not figure out why. The C++ dll was generated using vs2012 wizard, win32 application, dll with pre-head. It is built with x64 option. Here is the code:
// MyNativeDLL.cpp : Defines the exported functions for the DLL application.
//
#include "stdafx.h"
//char* pMemoryBuffer = NULL;
using namespace std;
__declspec(dllexport) long Test()
{
long a;
a = 1;
a++;
return a;
}
The C# code calling it is:
[DllImport("C:\\MyNativeDLL\\x64\\Debug\\MyNativeDLL.dll", EntryPoint = "Test")]
private extern static int Test();
void doJob()
{
long a = Test(); // exception thrown here
}
C# code is built with Any CPU option, and it is loading the x64 native dll.
I wondering where I did wrong? I have been trying long, but really get stuck here. Thanks!
UPDATE
When I compile my native dll using win 32 option, and set up correct dll path, it loads successfully. But when I compile my native dll with x64 options, load with correct path, the loading fails.
As you mentioned:
The C++ dll was generated using vs2012 wizard, win32 application, dll with pre-head. It is built with x64 option
The DLL and exe have to be both 32 bit, or both 64 bit.
I have a dll (Tracker.dll) compiled from C# and need to use it in native C++. I have that problem solved; since I cannot modify the C#, I am writing a managed C++ wrapper and exporting the classes accordingly. For a (simplified) example:
TrackerWrapper.h
#pragma once
#include <memory>
class __declspec(dllexport) TrackerWrapper {
public:
TrackerWrapper();
~TrackerWrapper();
void Track();
private:
struct Impl;
std::unique_ptr<Impl> pimpl;
};
TrackerWrapper.cpp
#using "Tracker.dll"
#include "TrackerWrapper.h"
#include <msclr\auto_gcroot.h>
using namespace System::Runtime::InteropServices;
struct TrackerWrapper::Impl {
msclr::auto_gcroot<Tracker^> tracker;
Impl() : tracker(gcnew Tracker()) {}
~Impl() {}
};
TrackerWrapper::TrackerWrapper() : pimpl(new Impl()) {}
TrackerWrapper::~TrackerWrapper() {}
void TrackerWrapper::Track() {
pimpl->tracker->Track();
}
Main.cpp
#include "TrackerWrapper.h"
int main() {
TrackerWrapper tracker;
tracker->Track();
return 0;
}
As long as all of the objects and binaries are in the same directory, after compiling with
cl /clr /LD TrackerWrapper.cpp
cl Main.cpp TrackerWrapper.lib,
everything runs perfectly. However, ideally we need the Tracker.dll as well as TrackerWrapper.lib and TrackerWrapper.dll to be in a separate directory, e.g. bin.
So, the directory structure might look like:
bin\
Tracker.dll
TrackerWrapper.dll
TrackerWrapper.lib
<other objects>
Main.cpp
TrackerWrapper.h
TrackerWrapper.cpp
I can get everything to compile by adding bin to my %PATH%, %LIB% and %LIBPATH% environment variables (or on the command line at compile time via /link and /AI), but when I execute the resulting executable I get the following error:
Unhandled Exception: System.IO.FileNotFoundException: Could not load file or assembly 'Tracker, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null' or one of its dependencies. The system cannot find the file specified.
at TrackerWrapper.Impl.{ctor}(Impl* )
at TrackerWrapper.{ctor}(TrackerWrapper* )
I have tried changing #using "Tracker.dll" to a relative as well as an absolute path, but I get the same problem.
Any ideas?
Two things you can try:
Check if there's inner exception in FileNotFoundException, if does,
it might give you details.
Monitor the process with process monitor from System internal, it can will log all file activity of the the process, from the log, you can tell which file is missing. Remember to the set the filter to only monitor your process, other wise it will monitor all processes.
Your library is loaded by the .net infrastructure and it only searches by default at the app directory or at the GAC.
If your app were .net then you can specify a library path in the App.config but as your app is native don't know if the mixed dll will load the App.config or not, may be you can try.
From MSDN:
You can use the < probing > element in the application configuration
file to specify subdirectories the runtime should search when locating
an assembly.
If that does not work then your last option is to add the libraries to the GAC, but the library will not really be in the specified folder but copied to the GAC's folder.
I am developing an add-in using VSTO for Microsoft project and I have a managed c++ dll that wraps an un-managed c++ dll. I need to deploy two versions of the managed c++ dll one for 64 bit and one for 32 bit. I am using Assembly.LoadFrom(path) to load the appropriate dll depending on which version of Office I am running from. This all seems to work fine on my development machine which is a 64 bit machine running 64 bit office. Below is the code in question:
try
{
//This will return true so I know the file exists
bool fileExists = File.Exists(path);
//This will throw a file not found exception
keyModAssembly = Assembly.LoadFrom(path);
}
catch (FileNotFoundException e)
{
}
I have triple checked the path and the file exists and is the correct 32 bit dll. This all works fine on my 64 bit machine but fails in xpmode when I am trying to test it for 32 bit versions.
any suggestions would be greatly appreciated.
Thanks in advance.
Edit
In response to Phillip's suggestion about the unmanaged dll possibly not being found I am loading the unmanaged dll into scope using the LoadLibraryW(path).
// this is not throwing an exception so I know the unmanaged dll is there.
if (!File.Exists(unmanagedPath))
throw new FileNotFoundException();
LoadLibraryW(unmangedlibPath);
Could it be that the wrapper assembly (which I assume is what path points to in your example) is loaded correctly, but the native DLL which it references is not found? You are not checking for that one in your code. Often the error message says 'Assembly or one of its dependencies is not found'.
A good way to investigate this is to use either procmon from the SysInternals tools to monitor the file system access (which will tell you where the system is looking for your 32-bit DLL) or use the Fushion facilities in Windows.
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.