非托管DLL的相对路径

本文关键字:相对 路径 DLL | 更新日期: 2023-09-27 18:24:10

可能重复:
在.NET 中指定DllImport的搜索路径

我有一个非托管DLL。为了获得许可,我想在C#代码中使用一个C++dll。问题是,它是一个windows应用程序,用户可以将其安装在自己选择的任何目录中。所以我不能用静态路径引用它,也找不到给出相对路径的方法。这是我尝试过的代码:

 [DllImport("mydll.dll", CharSet = CharSet.Auto, SetLastError = true)]
  static extern bool SetDllDirectory(string lpPathName);
  public void SetDllDirectory(string lpPathName)
        {
            try
            {
                bool r = SetDllDirectory(lpPathName);
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }
        public void SetDirectoryPath()
        {
            try
            {
                DirectoryInfo directory = new DirectoryInfo(System.IO.Path.GetDirectoryName(System.Windows.Forms.Application.ExecutablePath));
                if (directory.Exists)
                    SetDllDirectory(directory.ToString() + "''mydll.dll");
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

下面是我收到的错误。

在DLL"mydll.DLL"中找不到名为"SetDllDirectory"的入口点。

这个问题可能是的复制品

"C#中的C++非托管DLL"

"平台调用语句中DLL的相对路径"

很抱歉,但我在这些参考资料中找不到任何解决方案。

非托管DLL的相对路径

如果您试图将非托管库钉入非标准位置,则需要将此位置添加到windows用于查找dll文件的dll搜索路径中。

如果你的用户能告诉程序c/c++库文件在哪里,你可以在他们选择时手动加载它。

public class UnsafeNativeMethods {
    [DllImport("kernel32.dll", SetLastError = true)]
    public static extern bool SetDllDirectory(string lpPathName);
    [DllImport("kernel32.dll", SetLastError = true)]
    public static extern int GetDllDirectory(int bufsize, StringBuilder buf);
    [DllImport("kernel32", CharSet = CharSet.Unicode, SetLastError = true)]
    public static extern IntPtr LoadLibrary(string librayName);
    [DllImport("mylibrary")]
    public static extern void InitMyLibrary();
}

你可以用某种形式的预加载例程调用上面的内容,比如:

public void LoadDllFile( string dllfolder, string libname ) {
    var currentpath = new StringBuilder(255);
    UnsafeNativeMethods.GetDllDirectory( currentpath.Length, currentpath );
    // use new path
    UnsafeNativeMethods.SetDllDirectory( dllfolder );
    UnsafeNativeMethods.LoadLibrary( libname );
    // restore old path
    UnsafeNativeMethods.SetDllDirectory( currentpath );
}

你可以这样称呼它:

LoadDllFile( "c:'whatever", "mylibrary.dll" );

此错误消息:

在DLL"mydll.DLL"中找不到名为"SetDllDirectory"的入口点。

没有说找不到DLL。它说您的P/Invoke定义不正确。DLL(mydll.dll)中没有名为SetDllDirectory的函数。为什么要这样?从DLL导出的函数只有那些显式编码和导出的函数。由于您没有为SetDllDirectory编写代码并指示它应该从mydll.dll导出,因此它不存在于DLL中。

除此之外,这个问题是无法回答的,除非你用真实的代码更新你的问题。您至少需要发布尝试从非托管DLL调用的函数的签名,以及在C#(托管)端尝试的P/Invoke代码。

问题是,它是一个windows应用程序,用户可以将其安装在自己选择的任何目录中。所以我不能用静态路径引用它,也找不到给出相对路径的方法。

这不是一个真正的问题。相对路径工作得很好,它们的工作方式正是你的问题表明你已经尝试过的方式。您只需在P/Invoke定义中包含DLL的名称。默认的DLL搜索顺序会处理其他一切。如果托管EXE与要P/Invoke的非托管DLL位于同一目录中,则一切都将无缝工作。

用户选择在哪里安装应用程序并不重要,只要DLL和EXE位于同一文件夹中即可。这就是安装程序的工作。

只要使用相对路径,就绝对不需要使用Win32 API中的SetDllDirectory函数(它实际上是在kernel32.dll中定义的)。