ImageMagick on Azure Functions cannot load native library

0

I'm trying to use Magick.NET library to do image processing on Azure Functions.

I have tried the same code in a Console App (.NET Core 3.1) which works without any issues. However when running the same code in an Azure Functions Project, I get the following error.

Code:

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

Exception:

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

StackTrace:

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

Inner Exception:

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

Inner Exception StackTrace

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

I believe this is due to the way Azure Functions package is organized and the path Magick.NET is looking for its native binary to load. I can confirm that the native binary is written at \bin\Debug\netcoreapp3.1\runtimes\<platform>\native when the Function app is built.

I have traced the apps using ProcessMonitor for each app and can see Function app looks in the wrong location.

It looks in

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

instead of

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

(Below traces are filtered to only show path contains Magick.Native and process name filtered to the Console app exe and func.exe)

Console App Trace Console App Trace

Function App Trace Function App Trace

I have also tried setting MagickAnyCPU.CacheDirectory to Directory.GetCurrentDirectory() but it hasn't helped.


UPDATE:

After building, if I copy \netcoreapp3.1\runtimes folder to \bin this fixes the problem, but I current don't want to rely on that trick if there's a proper workaround.

UPDATE 2:

This issue appears to happen only when using <TargetFramework>netcoreapp3.1</TargetFramework> and Microsoft.NET.Sdk.Functions version 3.0.x

It does not appear when using older versions. I have successfully used <TargetFramework>netcoreapp2.1</TargetFramework> and Microsoft.NET.Sdk.Functions version 1.0.x without this issue.


So, is there a workaround to get ImageMagick to load native lib from the right place?


Potential Workaround is to get msbuild to copy the runtimes folder after the build completes.

Add following to csproj

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

or right click project > properties > Build Events and paste the above command to post build event command line

This will copy all of the runtimes binaries, not just the one we want, increasing the size of final build.

azure
imagemagick
azure-functions
azure-functions-core-tools
magicknet
asked on Stack Overflow Jul 4, 2020 by Madushan • edited Jul 5, 2020 by Madushan

1 Answer

0

UPDATE:

This may be a bug in Microsoft.NET.Sdk.Functions version 3.0.8. These issues in the github repo are tracking this.

  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

This seems to only happen when using Microsoft.NET.Sdk.Functions version 3.0.8 which seems to have only just appeared in nuget on Friday. I will instead downgrade to 3.0.7.

Alternatively if you don't want to downgrade,

You could use MagickNET.SetNativeLibraryDirectory as a work around

answered on Stack Overflow Jul 5, 2020 by Madushan • edited Jul 6, 2020 by Madushan

User contributions licensed under CC BY-SA 3.0