非托管DLL的相对路径

时间:2012-02-13 07:25:48

标签: c# windows dll unmanaged

  

可能重复:
  Specify the search path for DllImport in .NET

我有一个非托管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++ unmanaged DLL in c#

Relative Path to DLL in Platform Invoke Statement

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

2 个答案:

答案 0 :(得分:4)

如果您尝试将其转换为非标准位置的非托管库,则需要将此位置添加到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" );

答案 1 :(得分:1)

此错误消息:

  

无法在DLL“mydll.dll”中找到名为“SetDllDirectory”的入口点。

没有说明无法找到DLL。它表示您的P / Invoke定义不正确。您的DLL(SetDllDirectory)中没有名为mydll.dll的函数。为什么会这样?从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中定义)。