1

I have a DLL that I need to access methods from.

In most cases like this I just use [DllImport] to access methods from unmanaged assemblies, but the problem with that in this situation is that it requires the path to the DLL at instantiation time, so a constant string.

This particular DLL is one that gets installed with my application and I can't guarantee where it will be after the program is installed (I'd rather not put it somewhere static like %SystemRoot%).

So is there a way in C# that I can declare and use a method from a DLL at runtime with a variable path?

Any ideas or suggestions would be greatly appreciated!

4

3 回答 3

2

根本不要使用路径。Windows 在尝试从动态或静态加载函数时使用搜索 DLL 的默认方法。

确切的搜索逻辑记录在 MSDN 的LoadLibrary文档中- 基本上,如果 DLL 仅由您的应用程序使用,则在安装期间将其放在与您的应用程序相同的文件夹中,不用担心。如果是常用的 DLL,把它放在 LoadLibrary() 搜索到的文件夹结构中的某个位置,它就会被找到。

于 2009-04-10T19:22:56.233 回答
2

这有点hack,但是既然你说你可以在运行时找到dll的路径,为什么不在你使用任何函数之前将它复制到你当前的工作目录呢?这样,dll 将存在于您的 exe 旁边,并且会被 LoadLibrary 找到。在您的 DllImport 中不需要任何其他路径。

使用动态路径中的方法的唯一其他方法是执行以下操作: 1) 为LoadLibraryGetProcAddress
执行必要的 P/Invoke 签名 2) 从所需路径加载库 (LoadLibrary) 3) 找到所需的函数 (GetProcAddress ) 4) 将指针投射到委托Marshal.GetDelegateForFunctionPointer 5) 调用它。




当然,您需要以这种方式为要“导入”的每个函数声明一个委托,因为您必须将指针转换为委托。

于 2009-04-10T20:00:30.450 回答
0

我也有类似的情况。我使用安装在机器上的 SDK 中的 DLL。我从该 SDK 注册表项中获取 DLL 的目录位置。我在执行用户的 PATH 变量上设置了 DLL 位置(仅临时修改)。基本上,它允许您为要调用的 DLL 设置动态路径,因此不必来自注册表。请注意 PATH 变量是 Windows 查找 DLL 的最后一个位置。但另一方面,它不会改变 Windows 查找 DLL 的其他位置。

例子:

我想在 DLL 上调用的 API:

[DllImport("My.DLL")]
private static extern IntPtr ApiCall(int param);

获取注册表项(您需要使用 Microsoft.Win32;):

private static string GetRegistryKeyPath() {
        string environmentPath = null;

        using (var rk = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\SOMENNAME"))
        {
            if (rk != null)
            {
                environmentPath = rk.GetValue("Path(or whatever your key is)").ToString();
            }
            if (string.IsNullOrEmpty(environmentPath))
            {
                Log.Warn(
                    string.Format("Path not found in Windows registry, using key: {0}. Will default to {1}",
                         @"SOFTWARE\SOMETHING", @"C:\DefaultPath"));
                environmentPath = @"C:\DefaultPath";
            }
        }
        return environmentPath;
     }

在 PATH var 上添加 DLL 的路径(Concat() 在 Linq 中找到):

void UpdatePath(IEnumerable<string> paths){
    var path = new[] { Environment.GetEnvironmentVariable("PATH") ?? "" };
    path = path.Concat(paths);
    string modified = string.Join(Path.PathSeparator.ToString(), path);
    Environment.SetEnvironmentVariable("PATH", modified);
}

开始使用 API 调用:

var sdkPathToAdd = GetRegistryKeyPath();
IList<string> paths = new List<string>
        {
            Path.Combine(sdkPathToAdd),
            Path.Combine("c:\anotherPath")
        };
UpdatePath(paths);

//Start using
ApiCall(int numberOfEyes);
于 2015-08-14T13:43:05.770 回答