简体   繁体   English

天蓝色函数 c# .net 中的 DrawingCore 异常

[英]DrawingCore exception in azure function c# .net

Unhandled Exception: System.MemberAccessException :未处理的异常: System.MemberAccessException

Object is busy and cannot state allow this operation [GDI+ status: ObjectBusy]
       at System.DrawingCore.GDIPlus.CheckStatus(Status status)
       at System.DrawingCore.Image.Dispose(Boolean disposing)
       at System.DrawingCore.Image.Finalize()

This error occurs once in a while for following code.以下代码偶尔会发生此错误。 I am using sautinsoft library and imageFormat is of System.DrawingCore.Imaging.我正在使用 sautinsoft 库,而 imageFormat 是 System.DrawingCore.Imaging。

  using (Stream fs = pdfFile.OpenReadStream())
      {
        await Task.Run(() => _pdfFocus.OpenPdf(fs));
        if (_pdfFocus.PageCount > 0)
          {
            _pdfFocus.ImageOptions.ImageFormat = imageFormat;
            _pdfFocus.ImageOptions.Dpi = 100;
            _pdfFocus.ImageOptions.JpegQuality = 90;
            for (int i = 1; i <= _pdfFocus.PageCount; i++)
              {
                 await Task.Run(() => pdfPagesAsImageFileList.Add(_pdfFocus.ToImage(i)));
              }
            }
         Task.WaitAll();
       }

Like Marc said the azure has sandbox limitations, and mostly .net package to convert pdf to image need GDI and this is not supported.就像 Marc 所说的 azure 有沙箱限制,并且大多数将 pdf 转换为图像的 .net 包需要 GDI,这不受支持。 For now I only find one package to iplement it with .net.现在我只找到一个包来使用 .net 来实现它。 You could try with GhostScript and Magick.NET-Q16-AnyCPU to implement it.您可以尝试使用GhostScriptMagick.NET-Q16-AnyCPU来实现它。

After installing the Ghostscript , you will get the gsdll32.dll file in the bin folder.安装Ghostscript ,您将在 bin 文件夹中获得gsdll32.dll文件。 The below is my test code, copy the 02.pdf and gsdll32.dll to the kudu wwwroot folder.下面是我的测试代码,将02.pdfgsdll32.dll复制到kudu wwwroot文件夹下。

using System.Net.Http;
using ImageMagick;
using Microsoft.Azure.WebJobs;
using Microsoft.Azure.WebJobs.Extensions.Http;
using Microsoft.Azure.WebJobs.Host;

namespace FunctionApp6
{
    public static class Function1
    {
        [FunctionName("Function1")]
        public static void Run([HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)]HttpRequestMessage req, TraceWriter log,ExecutionContext context)
        {
            log.Info("C# HTTP trigger function processed a request.");

            MagickNET.SetGhostscriptDirectory(context.FunctionAppDirectory);
            log.Info(context.FunctionAppDirectory);
            MagickReadSettings settings = new MagickReadSettings();
            // Settings the density to 300 dpi will create an image with a better quality
            settings.Density = new Density(300, 300);

            using (MagickImageCollection images = new MagickImageCollection())
            {
                log.Info(context.FunctionAppDirectory + "\\02.pdf");
                // Add all the pages of the pdf file to the collection
                images.Read(context.FunctionAppDirectory+"\\02.pdf", settings);

                int page = 1;
                foreach (MagickImage image in images)
                {
                    log.Info(context.FunctionAppDirectory + "\\outpng" + page + ".png");
                    // Write page to file that contains the page number
                    image.Write(context.FunctionAppDirectory + "\\outpng" + page + ".png");
                    // Writing to a specific format works the same as for a single image
                    //image.Format = MagickFormat.Ptif;
                    //image.Write(SampleFiles.OutputDirectory + "Snakeware.Page" + page + ".tif");
                    page++;
                }
            }

            log.Info("convert finish");
        }
    }
}

And here is the result pic in azure.这是天蓝色的结果图片。

在此处输入图片说明

Azure Functions runs inside a secure environment, aka a sandbox. Azure Functions 在安全环境(也称为沙箱)中运行。 There are quite some limitations to this sandbox, all of them are described here: https://github.com/projectkudu/kudu/wiki/Azure-Web-App-sandbox这个沙箱有很多限制,所有限制都在这里描述: https : //github.com/projectkudu/kudu/wiki/Azure-Web-App-sandbox

In your specific case you are limited because the process does not have access to GDI32 as is mentioned on the page linked above:在您的特定情况下,您受到限制,因为该过程无法访问上面链接的页面中提到的 GDI32:

For the sake of radical attack surface area reduction, the sandbox prevents almost all of the Win32k.sys APIs from being called, which practically means that most of User32/GDI32 system calls are blocked.为了彻底减少攻击面,沙箱阻止了几乎所有的 Win32k.sys API 被调用,这实际上意味着大部分 User32/GDI32 系统调用被阻止。 For most applications this is not an issue since most Azure Web Apps do not require access to Windows UI functionality (they are web applications after all).对于大多数应用程序,这不是问题,因为大多数 Azure Web 应用程序不需要访问 Windows UI 功能(毕竟它们是 Web 应用程序)。

There are multiple libraries used to convert HTML to PDF.有多个库用于将 HTML 转换为 PDF。 Many Windows/.NET specific versions leverage IE APIs and therefore leverage User32/GDI32 extensively.许多 Windows/.NET 特定版本利用 IE API,因此广泛利用 User32/GDI32。 These APIs are largely blocked in the sandbox (regardless of plan) and therefore these frameworks do not work in the sandbox.这些 API 大部分都在沙箱中被阻止(无论计划如何),因此这些框架在沙箱中不起作用。

There are some frameworks that do not leverage User32/GDI32 extensively (wkhtmltopdf, for example) and we are working on enabling these in Basic+ the same way we enabled SQL Reporting.有一些框架没有广泛利用 User32/GDI32(例如 wkhtmltopdf),我们正在努力在 Basic+ 中启用这些,就像启用 SQL 报告一样。

You probably need to find an alternative way to create PDF files or move the compute outside of Azure Functions.您可能需要找到一种替代方法来创建 PDF 文件或将计算移到 Azure Functions 之外。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM