Search code examples
c#pdfaccess-violation.net-6.0dinktopdf

How To Ignore Access Violation Exception From External Dll - .NET Core 6


I'm using DinkToPDF dll to convert an XML to PDF.

I need to generate 2000 PDF's.

So I try to do put the PDF generation logic inside for loop. It generates first 2 or 3 PDF's and then in the next iteration crashes with a native Exception

This is my PDF generation class. Generate() method will be called 2000 times inside a forloop

public static class PDFEngine
{
    public static void Generate(string html, string directory, string fileName)
    {
        var converter = new BasicConverter(new PdfTools());

        converter.PhaseChanged += Converter_PhaseChanged;
        converter.ProgressChanged += Converter_ProgressChanged;
        converter.Finished += Converter_Finished;
        converter.Warning += Converter_Warning;
        converter.Error += Converter_Error;

        var doc = new HtmlToPdfDocument()
        {
            GlobalSettings = {
                ColorMode = ColorMode.Color,
                Orientation = Orientation.Portrait,
                PaperSize = PaperKind.A4,
            },
            Objects = {
                new ObjectSettings() {
                    PagesCount = true,
                    HtmlContent = html,
                    WebSettings = { DefaultEncoding = "utf-8" },
                    HeaderSettings = { FontSize = 9, Right = "Page [page] of [toPage]", Line = true },
                    FooterSettings = { FontSize = 9, Right = "Page [page] of [toPage]" }
                }
            }
        };

        byte[] pdf = converter.Convert(doc);

        if (!Directory.Exists(directory))
        {
            Directory.CreateDirectory(directory);
        }

        using (FileStream stream = new FileStream($"{directory}\\{fileName}", FileMode.Create))
        {
            stream.Write(pdf, 0, pdf.Length);
        }
    }

    private static void Converter_Error(object sender, DinkToPdf.EventDefinitions.ErrorArgs e)
    {
        Console.WriteLine("[ERROR] {0}", e.Message);
    }

    private static void Converter_Warning(object sender, DinkToPdf.EventDefinitions.WarningArgs e)
    {
        Console.WriteLine("[WARN] {0}", e.Message);
    }

    private static void Converter_Finished(object sender, DinkToPdf.EventDefinitions.FinishedArgs e)
    {
        Console.WriteLine("Conversion {0} ", e.Success ? "successful" : "unsucessful");
    }

    private static void Converter_ProgressChanged(object sender, DinkToPdf.EventDefinitions.ProgressChangedArgs e)
    {
        Console.WriteLine("Progress changed {0}", e.Description);
    }

    private static void Converter_PhaseChanged(object sender, DinkToPdf.EventDefinitions.PhaseChangedArgs e)
    {
        Console.WriteLine("Phase changed {0} - {1}", e.CurrentPhase, e.Description);
    }
}

System.AccessViolationException: 'Attempted to read or write protected memory. This is often an indication that other memory is corrupt.'

enter image description here

Since this is an Exception generating from an Unmanaged dll, I can't catch it. enter image description here

I tried adding

GC.Collect();
GC.WaitForPendingFinalizers();

during every loop but it's not working. I'm fully aware that this error is fatal and not good to continue but I don't have a way to process 2000 files.

Is there any other way to either

  1. Suppress the Exception and continue loop
  2. Resolve this error by running it in a different app domain or something?

Solution

  • After a lot of trial and error I was able to make it work with a different way.

    My intention is to run in 2000 times. My issue was when I put it inside the loop, I'm getting native exceptions

    To make it work for my need

    1. I removed the loop and generate PDF only for a single file. This file name I receive in a commandline argument

    2. Then I created another console app that got a 2000 iteration loop and it'll call the main app as a Process.Start(); I can pass the filename as arguments

    enter image description here

    This way I managed to make for any number of iterations for time being. Since each process got different PID now Memory issue is not there

    enter image description here