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)
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.
UPDATE:
This may be a bug in Microsoft.NET.Sdk.Functions
version 3.0.8
.
These issues in the github repo are tracking this.
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
User contributions licensed under CC BY-SA 3.0