Azure Functions 上的 ImageMagick 无法加载本机库

ImageMagick on Azure Functions cannot load native library

我正在尝试使用 Magick.NET 库在 Azure Functions 上进行图像处理。

我在控制台应用程序 (.NET Core 3.1) 中尝试了相同的代码,它可以正常工作。但是,当 运行 Azure Functions 项目中的相同代码时,出现以下错误。

代码:

var image = new MagickImage(File.ReadAllBytes(@"<My Image Path>"));

异常:

System.TypeInitializationException: 'The type initializer for 'NativeMagickSettings' threw an exception.'

堆栈跟踪:

at ImageMagick.MagickSettings.NativeMagickSettings..ctor()
at ImageMagick.MagickSettings..ctor()
at ImageMagick.MagickImage..ctor()
at ImageMagick.MagickImage..ctor(Byte[] data)
at FunctionApp2.Function1.Run(TimerInfo myTimer, ILogger log) <-- My Code

内部异常:

Unable to load DLL 'Magick.Native-Q8-x64.dll' or one of its dependencies: The specified module could not be found. (0x8007007E)

内部异常 StackTrace

at ImageMagick.Environment.NativeMethods.X64.Environment_Initialize()
at ImageMagick.Environment.NativeEnvironment.Initialize()
at ImageMagick.Environment.Initialize()
at ImageMagick.MagickSettings.NativeMagickSettings..cctor()

我认为这是由于 Azure Functions 包的组织方式和路径 Magick.NET 正在寻找要加载的本机二进制文件。我可以确认在构建 Function 应用程序时,本机二进制文件已写入 \bin\Debug\netcoreapp3.1\runtimes\<platform>\native

我已经使用 ProcessMonitor 跟踪了每个应用程序的应用程序,并且可以看到 Function 应用程序看起来在错误的位置。

它看起来在

\bin\Debug\netcoreapp3.1\ bin\ runtimes\[platform]\native

而不是

\bin\Debug\netcoreapp3.1\runtimes\[platform]\native

(以下跟踪被过滤为仅显示 path contains Magick.Native 和进程名称过滤到控制台应用程序 exe 和 func.exe)

Console App Trace

Function App Trace

我也试过将 MagickAnyCPU.CacheDirectory 设置为 Directory.GetCurrentDirectory(),但没有用。


更新:

构建后,如果我将 \netcoreapp3.1\runtimes 文件夹复制到 \bin,这可以解决问题,但如果有适当的解决方法,我目前不想依赖该技巧。

更新 2:

这个问题似乎只有在使用 <TargetFramework>netcoreapp3.1</TargetFramework>Microsoft.NET.Sdk.Functions 版本 3.0.x

使用旧版本时不会出现。我已经成功使用 <TargetFramework>netcoreapp2.1</TargetFramework>Microsoft.NET.Sdk.Functions 版本 1.0.x 没有这个问题。


那么,是否有解决方法让 ImageMagick 从正确的位置加载本机库?


可能的解决方法 是让 msbuild 在构建完成后复制 runtimes 文件夹。

将以下内容添加到 csproj

  <Target Name="PostBuild" AfterTargets="PostBuildEvent">
    <Exec Command="xcopy /Y /E $(OutDir)runtimes\ $(OutDir)bin\runtimes\" />
  </Target>

或者右击项目 > 属性 > 构建事件并将上面的命令粘贴到 post build event command line

这将复制所有 runtimes 二进制文件,而不仅仅是我们想要的二进制文件,从而增加最终构建的大小。

更新:

这可能是 Microsoft.NET.Sdk.Functions 版本 3.0.8 中的错误。 github 回购中的这些问题正在跟踪这个。

  1. Version 3.0.8 places the runtimes folder incorrectly
  2. Microsoft.Data.SqlClient is not supported on this platform with Microsoft.NET.Sdk.Functions 3.0.8

这似乎只有在使用 Microsoft.NET.Sdk.Functions 版本 3.0.8 时才会发生,该版本似乎只是在周五才出现在 nuget 中。我会降级到 3.0.7.

或者,如果您不想降级,

You could use MagickNET.SetNativeLibraryDirectory as a work around