【问题标题】:DrawingCore exception in azure function c# .net天蓝色函数c#.net中的DrawingCore异常
【发布时间】:2020-04-15 14:19:53
【问题描述】:

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

【问题讨论】:

    标签: c# .net-core azure-functions


    【解决方案1】:

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

    安装Ghostscript后,您将在bin文件夹中获得gsdll32.dll文件。下面是我的测试代码,将02.pdf和gsdll32.dll复制到kuduwwwroot文件夹中。

    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 中的结果图片。

    【讨论】:

    • 如果这可以帮助你,请接受它作为答案。
    • 我尝试了您的解决方案,但卡在了这个 **ImageMagick.MagickDelegateErrorException: 'FailedToExecuteCommand `"gswin32c.exe" **
    • 我曾经遇到过这个错误,重新上传gsdll32.dll文件后,重新发布并重新启动应用程序然后它就可以工作了,假设是因为gsdll32.dl不完整。
    【解决方案2】:

    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 之外。

    【讨论】:

    • 1.如果这是限制,而不是我在 5 次执行中出现一次错误的原因。 2.另外,在azure中部署代码后,我做了负载测试,它抛出了不同代码0x80070040、0x800704CD的COM异常,是因为这个限制吗?执行连续请求时会发生这种情况吗?
    猜你喜欢
    • 2011-06-14
    • 2014-08-21
    • 2013-05-03
    • 2018-03-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-12-28
    • 1970-01-01
    相关资源
    最近更新 更多