使用DllImport将非托管dll加载到托管应用程序中

3
在我的项目中,我有一个未经管理的本地C++ DLL和一个C#应用程序。我正在尝试使用DllImport从未经管理的DLL导入函数,但我一直收到DllNotFoundException。
以下是调用DLL的代码。
using System.Runtime.InteropServices;
namespace TestApp
{
  public delegate void UpdateDelegate(string s);
  class Program
  {
    [DllImport("CGPUnmanagedLibrary.dll")]
    internal static extern int parse_raw_gsod_file( 
      [MarshalAs(UnmanagedType.LPStr)]                                               
      string filePath,
      int minTemp, 
      UpdateDelegate callBack);

    static void Main(string[] args)
    {
      UpdateDelegate myCallBack = new UpdateDelegate(Program.Report);
      string path = @"C:\Creative Solutions\Projects\Clyde's Garden Planner\Frost Data Database\GSOD Data\GSOD_RAW_DATA\1992\gsod_1992.txt";
      int result = parse_raw_gsod_file(path, 32, myCallBack);
      Console.Write("Parse completed with exit code: " + result.ToString());
      Console.ReadLine();
    } // end main function

    public static void Report(string msg)
    {
      Console.Write("Message is ");
      Console.WriteLine(msg);
    }

  } // End class
} // end namespace

我尝试将DLL复制到应用程序输出目录,但它仍然找不到。我还尝试将DLL项目添加为引用,但弹出窗口显示无法添加。如何正确地将非托管DLL链接到托管应用程序? 更新 - 这是完整的错误信息:
Unable to load DLL 'CGPUnmanagedLibrary': The specified module could not be found. (Exception from HRESULT: 0x8007007E)
更新2 - 我确定DLL文件与试图加载它的.exe文件在同一目录中。这让我想到DLL文件中可能存在未加载的依赖项。我在DLL文件中只使用了基本的C++库(如string、math、iostream等)。有什么想法是哪些内容没有被加载以及原因吗? 更新3 - 使用Dependency Walker进行测试 在Dependency Walker中加载我的非托管C++ DLL文件时没有显示任何错误。我还尝试在Dependency Walker中打开我的可执行文件,结果显示有两个DLL文件无法加载:GPSVC.DLL和IESHIMS.DLL - 这没有任何意义,因为我的代码中只使用了标准的C++库。我认为这可能与我有一个托管C++/CLI DLL文件试图加载非托管DLL文件有关(我试图实现一些C++/CLI包装器)。无论如何,我已经开始了一个新的VS解决方案并继续前进。请参见我的答案。

可能与PATH变量有关,但我认为通常程序目录已经在其中了... - Jwosty
1
尝试删除dllimport中的“.dll”部分 - Sam Axe
尝试输入dll的完整路径。 - VladL
已删除 .dll 文件,但仍然出现错误。谢谢。 - nalyd88
我尝试了完整路径,但仍然显示找不到模块。我认为还有其他东西阻止了模块的加载... - nalyd88
4个回答

4

很可能问题不在您尝试加载的DLL上,而是它的一个(链接)依赖项。请在DLL上运行depends.exe或类似实用程序,以查看是否可以找到所有依赖项。这个误导性的消息“找不到指定的模块”已经成为经典的烦恼(如果不是FAQ材料!):它会让您认为无法找到您的DLL,而几乎所有时间都是它的某个依赖项无法找到。


2
为了进行测试,*.dll文件需要与试图加载它的.exe文件位于同一目录下。此时不要相信Visual Studio会为您完成这一步骤。请将该文件物理复制到C:*\*****\Debug\x86\bin\或者您正在运行的任何其他配置中。如有疑问,请将其复制到所有bin文件夹中。找到路径后,然后开始寻找自动化项目构建以正确复制文件的方法。如果这样做还不行,请将其放入system32--它肯定会在那里找到它。但是,如果在执行这些操作后仍然找不到它,则可能存在对未管理的dll的依赖项也丢失了。

0
首先,我想感谢每个人的帮助。不幸的是,我从未解决过这个问题(请参见我的主要问题中的编辑)。答案是开始一个全新的Visual Studio解决方案并创建两个新项目:C#应用程序和C++ dll。我取消了包装器的需要,因为现在只是调用两个主要函数。

再次感谢。


0

用户arayq2的回答非常有道理,我很快就能解决我的问题了。

在我的情况下,无法加载的dll(DllNotFoundException)依赖于另一个dll。这个dll(不是我的项目的一部分)实际上是使用较新版本的某些.h和.lib文件进行编译的。无法加载的dll所编译的项目中包含了旧版本的这些同名.h和.lib文件。

在我更新了我的dll项目,并重新编译了我的dll项目后,我的问题得到了解决。

谢谢arayq2!


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接