如何在ASP.NET中包含libsodium.net

10

我有一个基于 ASP.NET 构建的旧 webservice(使用 .asmx 文件)。我需要使用 sodium.net - 可惜在加载依赖的 libsodium.dll 文件时失败了。你们有什么关于我做错了什么的想法吗?

  • 我已通过 NuGet 添加了 libsodium.net。

  • 我已将 64 位 DLL 重命名为 "libsodium.dll"(还尝试了其他命名约定)。

  • 我试着直接引用 libsodium.dll,但 VS 拒绝它(不是有效的 DLL)。因此,我将其作为 "content" 添加,并使用 "copy to output"。

  • 构建后,我可以看到网站/Bin 文件夹中包含 sodium.dll(.NET 程序集)和 libsodium.net。

  • 当我尝试使用 libsodium.net 时,我得到以下错误:

    ERROR 2015-02-02 11:14:27,118 13798ms [41] CabinetService doRequest - Caught: The type initializer for 'Sodium.SodiumCore' threw an exception. System.TypeInitializationException: The type initializer for 'Sodium.SodiumCore' threw an exception. ---> System.DllNotFoundException: Unable to load DLL 'libsodium.dll': The specified module could not be found. (Exception from HRESULT: 0x8007007E) at DynamicDllInvokeType.sodium_init() at Sodium.SodiumCore..cctor() --- End of inner exception stack trace --- at Sodium.SodiumCore.LibraryName() at Sodium.SecretBox.Create(Byte[] message, Byte[] nonce, Byte[] key) at Macaroons.SecretBoxCryptoAlgorithm.Encrypt(Byte[] key, Byte[] plainText) in c:\Projects\Macaroons.Net\Macaroons.Net\SecretBoxCryptoAlgorithm.cs:line 58

因此,它无法找到“libsodium.dll”,即使它在 Bin 文件夹中。我还尝试删除对“sodium.net”的依赖关系,然后得到一个运行时错误,说“sodium.net”丢失了-当我重新添加它时,该错误消失了,而上面的错误出现了(表明“sodium.net”正确加载)。

所以我打开 "C:\Windows\Microsoft.NET\Framework\v4.0.30319\Temporary ASP.NET Files\cabinetservice" 中的网站影子文件夹并搜索 "sodium"。唯一的结果是在某个子文件夹中的 "sodium.dll"。没有 "libsodium.dll"。
显然,ASP.NET 在创建网站的影子副本时忽略了 "libsodium.dll" 文件。
我还尝试将 libsodium.dll(32位)添加到 C:\Windows\System32 和 libsodium.dll(64位)添加到 C:\Windows\SysWOW64。同样的结果。
并且我尝试了 C:\Windows\Microsoft.NET\assembly\GAC_32\libsodium 和 C:\Windows\Microsoft.NET\assembly\GAC_64\libsodium。同样的结果。
如何使 ASP.NET 知道这个依赖项?
2个回答

20

事实证明,ASP.NET不会对像libsodium.dll和libsodium-64.dll这样的非托管DLL进行阴影副本。

Sodium.dll(受管理的代码)试图从与Sodium.dll的阴影副本相同的目录(这是不起作用的)或PATH环境变量目录中的某个位置加载DLL。

我的解决方案是在调用任何Sodium代码之前将AppDomain \Bin目录添加到路径中:

// Make it possible to load unmanaged libsodium DLLs that .NET does not make shadow copies of.
// -> Simply point the "path" variable to the Bin directory.
string path = Environment.GetEnvironmentVariable("PATH");
string binDir = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Bin");
Environment.SetEnvironmentVariable("PATH", path + ";" + binDir);

2018年1月更新(来自Jordan Rieger的回答):

请注意,您可能还需要在服务器上安装Microsoft Visual C++ 2015可再发行版本(根据您的进程选择x64或x86目标)。

安装可再发行版本后,不要忘记重新启动应用程序池(我进行了IIS重置)。


1
我将该片段添加到了Global.asax.cs的Application_Start中,并且对于我的Web Forms应用程序非常有效。我通过NuGet添加了libsodium-net。 - Reuben
1
@Jørn Wildt 感谢您发布这篇文章,当我将其添加到我的全局应用程序启动时,它在本地工作正常。然而,当我在服务器上使用我的 Web 发布时,我遇到了相同的错误。:( - Gram
这对我在Azure App Service上使用ASP.NET(4.6)和MVC(5)有效。谢谢! - guysherman

2
请注意,在服务器上安装Microsoft Visual C++ 2015可再发行程序包(根据您的进程,选择x64或x86目标)可能也是必需的。
在安装可再发行程序包后,不要忘记重新启动应用程序池(我执行了IIS重置)。
请参阅我的评论https://dev59.com/ZVoU5IYBdhLWcg3wi3aX#45078280

是的,几周前我也遇到了完全相同的问题。 - Jørn Wildt

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