繁体   English   中英

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

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

未处理的异常: 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()

以下代码偶尔会发生此错误。 我正在使用 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();
       }

就像 Marc 所说的 azure 有沙箱限制,并且大多数将 pdf 转换为图像的 .net 包需要 GDI,这不受支持。 现在我只找到一个包来使用 .net 来实现它。 您可以尝试使用GhostScriptMagick.NET-Q16-AnyCPU来实现它。

安装Ghostscript ,您将在 bin 文件夹中获得gsdll32.dll文件。 下面是我的测试代码,将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");
        }
    }
}

这是天蓝色的结果图片。

在此处输入图片说明

Azure Functions 在安全环境(也称为沙箱)中运行。 这个沙箱有很多限制,所有限制都在这里描述: https : //github.com/projectkudu/kudu/wiki/Azure-Web-App-sandbox

在您的特定情况下,您受到限制,因为该过程无法访问上面链接的页面中提到的 GDI32:

为了彻底减少攻击面,沙箱阻止了几乎所有的 Win32k.sys API 被调用,这实际上意味着大部分 User32/GDI32 系统调用被阻止。 对于大多数应用程序,这不是问题,因为大多数 Azure Web 应用程序不需要访问 Windows UI 功能(毕竟它们是 Web 应用程序)。

有多个库用于将 HTML 转换为 PDF。 许多 Windows/.NET 特定版本利用 IE API,因此广泛利用 User32/GDI32。 这些 API 大部分都在沙箱中被阻止(无论计划如何),因此这些框架在沙箱中不起作用。

有一些框架没有广泛利用 User32/GDI32(例如 wkhtmltopdf),我们正在努力在 Basic+ 中启用这些,就像启用 SQL 报告一样。

您可能需要找到一种替代方法来创建 PDF 文件或将计算移到 Azure Functions 之外。

暂无
暂无

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

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