Azure-Functions icon indicating copy to clipboard operation
Azure-Functions copied to clipboard

Referencing external assembly with native dependencies in Azure Function

Open dovisio opened this issue 6 years ago • 45 comments

I'm getting following exception when doing aforementioned:

2017-12-10T12:56:29.526 Function started (Id=22fce544-1d7f-4262-8c59-dcb962ac0bd1)2017-12-10T12:56:29.574 Exception during runtime resolution of assembly 'Affdex, Version=3.4.1.1320, Culture=neutral, PublicKeyToken=null': 'System.IO.FileLoadException: Could not load file or assembly 'Affdex, Version=3.4.1.1320, Culture=neutral, PublicKeyToken=null' or one of its dependencies. Attempt to load an unverifiable executable with fixups (IAT with more than 2 sections or a TLS section.) (Exception from HRESULT: 0x80131019)File name: 'Affdex, Version=3.4.1.1320, Culture=neutral, PublicKeyToken=null' ---> System.IO.FileLoadException: Attempt to load an unverifiable executable with fixups (IAT with more than 2 sections or a TLS section.) (Exception from HRESULT: 0x80131019) at System.Reflection.RuntimeAssembly.nLoadImage(Byte[] rawAssembly, Byte[] rawSymbolStore, Evidence evidence, StackCrawlMark& stackMark, Boolean fIntrospection, SecurityContextSource securityContextSource) at System.Reflection.Assembly.Load(Byte[] rawAssembly) at Microsoft.Azure.WebJobs.Script.Description.FunctionMetadataResolver.ResolveAssembly(String assemblyName) in C:\projects\azure-webjobs-sdk-script\src\WebJobs.Script\Description\DotNet\FunctionMetadataResolver.cs:line 232 at Microsoft.Azure.WebJobs.Script.Description.FunctionAssemblyLoadContext.ResolveAssembly(String name) in C:\projects\azure-webjobs-sdk-script\src\WebJobs.Script\Description\DotNet\FunctionAssemblyLoadContext.cs:line 61 at Microsoft.Azure.WebJobs.Script.Description.FunctionAssemblyLoader.ResolveAssembly(Object sender, ResolveEventArgs args) in C:\projects\azure-webjobs-sdk-script\src\WebJobs.Script\Description\DotNet\FunctionAssemblyLoader.cs:line 60'2017-12-10T12:56:29.574 Unable to find assembly 'Affdex, Version=3.4.1.1320, Culture=neutral, PublicKeyToken=null'. Are you missing a private assembly file?2017-12-10T12:56:29.635 Exception while executing function: Functions.HttpTriggerCSharp1. mscorlib: Exception has been thrown by the target of an invocation. f-HttpTriggerCSharp1__-1535649923: Could not load file or assembly 'Affdex, Version=3.4.1.1320, Culture=neutral, PublicKeyToken=null' or one of its dependencies. The system cannot find the file specified.2017-12-10T12:56:29.729 Function completed (Failure, Id=22fce544-1d7f-4262-8c59-dcb962ac0bd1, Duration=211ms)

AffdexWrapper is using .NET library Affdex.dll which is in turn using affdex-native.dll and opencv_ffmpeg248.dll. All for libraries are in the same folder in the root of the app. Affdex documentation mentions that it requires Visual C++ Redistributable runtime for VS 2013

Are there any solutions at this point of time?

Dovydas

dovisio avatar Dec 10 '17 12:12 dovisio

What is the bitness of the assembly that you are trying to load, 32-bit or 64-bit? For native assemblies the bitness has to match. The default bitness for azure functions is 32.

patricklee2 avatar Dec 12 '17 22:12 patricklee2

referencing 32 bit libraries and function is 32 bit too. Also I have to mention that function is running from .csx file

dovisio avatar Dec 13 '17 13:12 dovisio

Can you provide steps to reproduce this error?

patricklee2 avatar Dec 14 '17 22:12 patricklee2

I have pushed Azure Function project to below repository: https://github.com/dovisio/AffdexFunctionApp32bit

This project works fine locally but fails to load when deployed to Azure. Thanks in advance

dovisio avatar Dec 15 '17 12:12 dovisio

I was unable to run the project locally. affdex-native.dll and opencv_ffmpeg248.dll could not be added as references in the project and I was unable to load Affdex.dll. What were the steps you took to install these dlls?

patricklee2 avatar Dec 18 '17 22:12 patricklee2

Can you try running through the steps at https://blogs.msdn.microsoft.com/benjaminperkins/2017/04/13/how-to-add-assembly-references-to-an-azure-function-app/

patricklee2 avatar Dec 19 '17 01:12 patricklee2

affdex-native.dll and opencv_ffmpeg248.dll cannot be added as references because they both are native libraries.

Affdex.dll works as (I suspect) a CLI/C++ bridge for .NET application.

Affdex.dll is already referenced and project should work locally, but fail when deployed to Azure functions. What errors are you getting? This link might help you https://knowledge.affectiva.com/v3.2/docs/getting-started-with-the-emotion-sdk-for-windows

dovisio avatar Dec 19 '17 09:12 dovisio

Can you try running through the steps at https://blogs.msdn.microsoft.com/benjaminperkins/2017/04/13/how-to-add-assembly-references-to-an-azure-function-app/

This suggestion does not make sense. I have no problem adding managed dependencies.

I'm suspecting that VC++ Redistributable packages are not loading somewhere in the dependency chain. Azure functions environment being a restricted sandbox, I cannot check fusion logs or install missing dependencies etc.

Related issue #https://github.com/Azure/azure-webjobs-sdk-script/issues/1469

dovisio avatar Dec 19 '17 09:12 dovisio

I am using a nuget library which uses CLI/C++ dll which could not load in Azure Functions but loads correctly on my machine. This dll which needs to be loaded is used to load native dll and run some processes. Will this kind of thing ever be supported? If not, what do you suggest I use instead of Azure Functions? Currently I am using Classic Cloud Services which starts full blown Windows 10 VM.

dejanberic avatar Jan 24 '19 12:01 dejanberic

Updating this issue in that I believe a number of improvements have been made here with Functions v2. It would be worth trying with latest v2 Functions (.NET Core). Not supported for functions v1

jeffhollan avatar Sep 04 '19 19:09 jeffhollan

Is there really no support for native libraries? I'm trying to use the Skiasharp library which works perfectly fine locally but when I deploy to Azure it can't find the assembly. See my issue created here.

I'm using app service too so I don't understand why it can't load/find the assembly. Am I really going to have to scrap functions entirely over this one library?

VividDigital avatar Nov 07 '19 14:11 VividDigital

If your native library requires a dynamically linked library by itself it will most likely fail to load in an environment that doesn't let you install these pre-requirements. I suggest building your native library with statically linked dependencies. If that isn't possible I don't think there is an easy way to get around this issue.

Gillibald avatar Nov 12 '19 16:11 Gillibald

Yes native dependencies are definitely supported but need to make sure the library includes them as well as a valid “runtimes” folder and metadata so the .NET host can load in the right native dependencies for the platform

jeffhollan avatar Nov 12 '19 16:11 jeffhollan

I've managed to get this working and it seems the issue was what I initially noticed was different in the issue I referenced in my first post.

When the app is published via VS2019, the runtimes folder gets published to wwwroot. Locally it gets published INSIDE the bin folder. Locally it works and on the server it doesn't.

Uploading the runtimes folder into the bin via ftp wouldn't work because access issues. Same goes with kudu, so I left it at that. Then today I realized I might be able to do it if I don't publish from package(zip). I created a new project and published the other way and that allows writing to the bin so I uploaded the runtimes folder into the bin and it works now.

What is the reason the publishing works differently when deploying? Is this a bug or do I need to do something on my end to make sure it gets published correctly within the bin? I'd like to run from package and not have to manually upload the runtimes folder each time I deploy.

VividDigital avatar Nov 12 '19 19:11 VividDigital

I resolved the same issue by adding libSkiaSharp.dll for win-x86 into the project and specifying “Copy to Output Directory” option in its properties to “Copy Always” value. In this case libSkiaSharp.dll is placed next to SkiaSharp.dll and it works properly. Hope this helps.

AlexNosk avatar Nov 18 '19 07:11 AlexNosk

@fabiocav curious to get your thoughts here. There's been a few libraries we've run into that aren't getting the bin's correctly copied into the internal bin folder. Is this a thing the functions SDK should be doing, or potentially an issue with how the libraries are communicating dependencies?

jeffhollan avatar Nov 18 '19 16:11 jeffhollan

The comment above leads me to believe this is a defect with the publishing logic and something we need to look at.

@VividDigital do you have a project sample with a repro we can look at? Want to make sure I'm working with your exact setup to rule out any differences in the project configuration.

fabiocav avatar Nov 18 '19 18:11 fabiocav

I created a basic function that replicates the issue. Publishes runtimes folder inside bin locally but outside when deployed. FunctionRuntimesExample.zip

VividDigital avatar Nov 18 '19 20:11 VividDigital

Having the same issue with SkiaSharp running in v3-preview function. Even though the /runtimes folder, which includes the native libraries, is published next to the /bin folder yet I am still getting Unable to load DLL 'libSkiaSharp' or one of its dependencies: The specified module could not be found. (0x8007007E)

alaatm avatar Nov 19 '19 17:11 alaatm

Adding the following to function project file seem to solve the problem:

<Target Name="PostPublish" AfterTargets="AfterPublish">
    <Exec Command="move $(PublishDir)\runtimes $(PublishDir)\bin" Condition=" '$(OS)' == 'Windows_NT' " />
    <Exec Command="mv $(PublishDir)\runtimes $(PublishDir)\bin" Condition=" '$(OS)' != 'Windows_NT' " />
</Target>

alaatm avatar Nov 19 '19 18:11 alaatm

I just want to add my 2c here. I think this is not really a question, but a bug or a missing feature. Unless, the documentation needs to me more explicit that a Function App does not work the same way as the rest of .NET Core.

The reason I say this is that with all things .NET Core and NuGet, if there is a native binary in the runtimes folder, then at runtime it is loaded so that the managed app can use (via p/invoke for example) that native binary. This works with console apps, websites, and pretty much everything else. If this is not supported, then why even copy the runtimes folder in the first place?

I hope we get native native support. 😉

Copying from @alaatm, I used MSBuild things to copy files:

<Target Name="CopyRequiredNativeAssets" AfterTargets="Publish">
  <ItemGroup>
    <NativeAssetToCopy Include="$(PublishDir)runtimes\win-x86\native\libSkiaSharp.dll" />
  </ItemGroup>
  <Copy SourceFiles="@(NativeAssetToCopy)" DestinationFolder="$(PublishDir)bin" />
</Target>

I noticed was that the runtime is 32-bit? Seems to be 64-bit hardware but 32-bit OS.

mattleibow avatar Nov 20 '19 05:11 mattleibow

@fabiocav I have a test repo here with the extra target to get it to work: https://github.com/mattleibow/SkiaSharpFunctions You should just be able to delete that snippet and see the error appear.

mattleibow avatar Nov 20 '19 06:11 mattleibow

Would be great to have some updates on the problem soon because we switched in our project from Azure App Service backend to Function App backend and now we are facing the same issue with SkiaSharp (we e.g. use it for image downscaling etc.). So now we now have the problem we can't use SkiaSharp with Azure Functions on production environment. We don't get it to work. Even the post of @mattleibow did not work in our case (Azure Function v2 Runtime & .NET Core 2.2).

So for now the only way for us is to look for an alternative to SkiaSharp that works with Azure Function v2 Runtime & .NET Core 2.2 or switching in our XAMARIN Native application back to our Azure App Service backend.

BHuber-PlanB avatar Nov 25 '19 10:11 BHuber-PlanB

@BernhardHuberPlanBGmbH do you have a Linux or a windows function? If you are using a Linux function, you may need to include https://www.nuget.org/packages/SkiaSharp.NativeAssets.Linux/ and copy libSkiaSharp.so instead.

mattleibow avatar Nov 25 '19 11:11 mattleibow

@mattleibow Thanks for the quick reply! We are using a windows function.

BHuber-PlanB avatar Nov 25 '19 11:11 BHuber-PlanB

And manually copying the libSkiaSharp.dll doesn't work? It is working in this example: https://github.com/mattleibow/SkiaSharpFunctions

https://skiasharpfunctions.azurewebsites.net/api/images?text=SkiaSharp%20Functions

mattleibow avatar Nov 25 '19 12:11 mattleibow

@mattleibow When manually copying the libSkiaSharp.dll to .../bin i receive the following message: Could not evaluate 'libSkiaSharp.dll' for extension metadata. Exception message: Bad IL format.

BHuber-PlanB avatar Nov 25 '19 12:11 BHuber-PlanB

That is just a warning, so you can ignore that. The function tasks are trying to process it, but they shouldn't. Probably a bug or we need some way to ignore that. I'll have a look and see maybe there is something.

mattleibow avatar Nov 25 '19 15:11 mattleibow

@mattleibow I manually copied libSkiaSharp.dll to bin directory. After that I tried to publish the Azure Function to Azure via Visual Studio publish functionality. Then the error message 'Could not evaluate 'libSkiaSharp.dll' for extension metadata. Exception message: Bad IL format.' occurred. I reviewed the files of the Azure Function via App Service Editor. libSkiaSharp.dll wasn't uploaded to Azure.

BHuber-PlanB avatar Nov 26 '19 15:11 BHuber-PlanB

@BernhardHuberPlanBGmbH Hmm. Maybe the VS publish option doesn't like this. I'll see if I can adjust some things in the target to only copy AFTER the processing has been done.

mattleibow avatar Nov 27 '19 06:11 mattleibow