DinkToPdf icon indicating copy to clipboard operation
DinkToPdf copied to clipboard

Qt: Could not initialize OLE (error 80010106)

Open mboukhlouf opened this issue 3 years ago • 15 comments

I'm working on a ASP.NET Core MVC app and I wanted to use DinkToPdf library to convert Html to PDF. I get this error in the console, when I first access a page that uses the IConverter from the services:

Qt: Could not initialize OLE (error 80010106)

I still get the PDF with no issues. I think the issue is somewhere around calling: new SynchronizedConverter(new PdfTools()) As I have it in the services as a singleton and only called the first time it's accessed:

services.AddSingleton(typeof(IConverter), new SynchronizedConverter(new PdfTools()));

mboukhlouf avatar Aug 10 '20 09:08 mboukhlouf

Have the same problem. It genereates the PDF, yet, the error is throw on the first call

Cafnio avatar Aug 10 '20 16:08 Cafnio

The same error is reported by the BasicConverter under the same conditions.

PeterWone avatar Mar 16 '21 04:03 PeterWone

Also getting this issue with OPs setting, I get this error with Haukcode.Wkhtmltopdf.netcore also... I think this is an issue with wkhtmltopdf.... but not sure. Can we get a point in the right direction? image

leijae avatar Apr 15 '21 18:04 leijae

I've abandoned wkhtmltopdf in favour of Chrome based solutions. Similar concept but using the debugging protocol to control headless Chrome. The wrappers aren't as mature but the handling of CSS and things like SVG are so much better it's not funny.

PeterWone avatar Apr 15 '21 21:04 PeterWone

That's awesome for you, but not sure how that helps when trying to generate thousands of pdfs as a background task in an azure function.

leijae avatar Apr 15 '21 22:04 leijae

I've not written an Azure function but if you're using wkhtmltopdf that implies you can at least load a DLL.

An exe might not work directly in an Azure function but what stops you from using more appropriate hosting to implement HTML to PDF as a web service and using it that way? Generation time is a few hundred ms for single page documents.

If that's not good enough, Chromium is open source. Contribute a direct API and make yourself very popular.

PeterWone avatar Apr 15 '21 22:04 PeterWone

I am seeing the same message. But it is still generating the PDF. Using .NET 5

WalissonPires avatar Apr 29 '21 21:04 WalissonPires

I've just hit this problem too, in an Azure Isolated Functions host project.

I'm pretty sure this issue is due to the worker thread in SynchronizedConverter not being STA mode. So I copied the SynchronizedConverter and made an STA version.

public class STASynchronizedConverter : BasicConverter
{
    Thread conversionThread;

    BlockingCollection<Task> conversions = new BlockingCollection<Task>();

    bool kill = false;

    private readonly object startLock = new object();

    public STASynchronizedConverter(ITools tools) : base(tools)
    {
    }

    public override byte[] Convert(IDocument document)
    {
        return Invoke(() => base.Convert(document));
    }

    public TResult Invoke<TResult>(Func<TResult> @delegate)
    {
        StartThread();

        Task<TResult> task = new Task<TResult>(@delegate);

        lock (task)
        {
            //add task to blocking collection
            conversions.Add(task);

            //wait for task to be processed by conversion thread
            Monitor.Wait(task);
        }

        //throw exception that happened during conversion
        if (task.Exception != null)
        {
            throw task.Exception;
        }

        return task.Result;
    }

    private void StartThread()
    {
        lock (startLock)
        {
            if (conversionThread == null)
            {
                conversionThread = new Thread(Run)
                {
                    IsBackground = true,
                    Name = "wkhtmltopdf worker thread"
                };

                // This is to fix issue https://github.com/rdvojmoc/DinkToPdf/issues/119
                conversionThread.SetApartmentState(ApartmentState.STA);

                kill = false;

                conversionThread.Start();
            }
        }
    }

    private void StopThread()
    {
        lock (startLock)
        {
            if (conversionThread != null)
            {
                kill = true;

                while (conversionThread.ThreadState == ThreadState.Stopped)
                { }

                conversionThread = null;
            }
        }
    }

    private void Run()
    {
        while (!kill)
        {
            //get next conversion taks from blocking collection
            Task task = conversions.Take();

            lock (task)
            {
                //run taks on thread that called RunSynchronously method
                task.RunSynchronously();

                //notify caller thread that task is completed
                Monitor.Pulse(task);
            }
        }
    }
}

distantcam avatar Jun 28 '21 02:06 distantcam

I also see this error. I can run this in an Azure function app once - it generates the PDF fine and throws this error, however subsequent calls to the function app fail (502 / 503 or just timeout / hang until I cancel the request)

Cactusman07 avatar Jul 11 '21 13:07 Cactusman07

I resolved the issue of failing to produce the second call to the Azure function by creating a startup class to handle the singleton

using Microsoft.Azure.Functions.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection;
using DinkToPdf;
using DinkToPdf.Contracts;

[assembly: FunctionsStartup(typeof(Html2Pdf.Startup))]

namespace Html2Pdf
{
    public class Startup : FunctionsStartup
    {
        public override void Configure(IFunctionsHostBuilder builder) 
        {
            builder.Services.AddSingleton(typeof(IConverter), new SynchronizedConverter(new PdfTools()));
        }
    }
}

See here for more https://docs.microsoft.com/en-us/azure/azure-functions/functions-dotnet-dependency-injection

jombard avatar Oct 18 '21 15:10 jombard

Hey,

I am using the library with .Net 5 console app. I am facing the same error

Qt: Could not initialize OLE (error 80010106)

This is my code:

` static void Main(string[] args) { 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.Landscape,
                PaperSize = PaperKind.A4,
            },
            Objects = {
                new ObjectSettings() {
                    PagesCount = true,
                    HtmlContent = @"Lorem ipsum dolor sit amet, consectetur adipiscing elit. In consectetur mauris eget ultrices iaculis. Ut et odio viverra, molestie lectus nec, venenatis turpis. Nulla quis euismod nisl. Duis scelerisque eros nec dui facilisis, sit amet porta odio varius. Praesent vitae sollicitudin leo. Sed vitae quam in massa eleifend porta. Aliquam pulvinar orci dapibus porta laoreet. Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Sed commodo tortor eget dolor hendrerit dapibus.
                                    Vivamus lorem diam, vulputate at ultrices quis, tristique eu nunc. Sed bibendum hendrerit leo. Nulla nec risus turpis. Vivamus at tortor felis. Donec eget posuere libero. Pellentesque erat nunc, molestie eget gravida vitae, eleifend a eros. Integer in tortor sed elit aliquam vehicula eget a erat. Vivamus nisi augue, venenatis ut commodo vel, congue id neque. Curabitur convallis dictum semper. Nulla accumsan urna aliquet, mattis dolor molestie, fermentum metus. Quisque at nisi non augue tempor commodo et pretium orci.
                                    Quisque blandit libero ut laoreet venenatis. Morbi sit amet quam varius, euismod dui et, volutpat felis. Sed nec ante vel est convallis placerat. Morbi mollis pretium tempor. Aliquam luctus eu justo vitae tristique. Sed in elit et elit sagittis pharetra sed vitae velit. Proin eget mi facilisis, scelerisque justo in, ornare urna. Aenean auctor ante ex, eget mattis neque pretium id. Aliquam ut risus leo. Vivamus ullamcorper et mauris in vehicula. Maecenas tristique interdum tempus. Etiam mattis lorem eget odio faucibus, in rhoncus nisi ultrices. Etiam at convallis nibh. Suspendisse tincidunt velit arcu, a volutpat nulla euismod sed.
                                    Aliquam mollis placerat blandit. Morbi in nibh urna. Donec nisl enim, tristique id tincidunt sed, pharetra non mi. Morbi viverra arcu vulputate risus dignissim efficitur. Vivamus dolor eros, finibus et porttitor a, pellentesque a lectus. Integer pellentesque maximus velit sit amet sollicitudin. Nulla a elit eget augue pretium luctus quis eu metus. Aenean nec dui id nibh tempor dapibus. Pellentesque dignissim ullamcorper mauris, vitae pharetra turpis sodales sit amet. Etiam et bibendum neque.
                                    Nulla gravida sit amet velit eu aliquet. Etiam sit amet elit leo. Sed nec arcu tincidunt, placerat turpis quis, laoreet nulla. Aenean neque est, fringilla non nulla in, laoreet vehicula nunc. Etiam vel nisl sit amet lectus pellentesque eleifend. Etiam sed nisi dolor. Mauris quis tincidunt ex. Aliquam porta mattis tempor. Maecenas fringilla bibendum elementum. Vestibulum quis tempus libero, vitae cursus neque. Suspendisse lectus risus, lacinia consectetur enim quis, ullamcorper porta tortor. Lorem ipsum dolor sit amet, consectetur adipiscing elit.",
                    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("Files"))
        {
            Directory.CreateDirectory("Files");
        }

        using (FileStream stream = new FileStream(@"Files\" + DateTime.UtcNow.Ticks.ToString() + ".pdf", FileMode.Create))
        {
            stream.Write(pdf, 0, pdf.Length);
        }

        Console.ReadKey();
        Console.WriteLine("Hello World!");
    }`

Any resolution so far?

Workaholic01 avatar Mar 14 '22 11:03 Workaholic01

@distantcam provided the solution. It works fine @Workaholic01. Those who may be checking this page in search of a solution, implement the solution by @distantcam. works for dotnet 6 .. @distantcam Thanks for the solution

ghost avatar Jul 11 '22 19:07 ghost

@distantcam solution works fine on Windows, but the function SetApartmentState is not available on Linux. Is there something that works on both platforms?

krasnyd avatar Jul 16 '22 15:07 krasnyd

Thanks, @distantcam it is work.

only notice for all, To access the Converter class, you must inject it, not create a new instance.

public YourService(IIConverter converter) 
{
        _converter = converter;
}

zanyar3 avatar Jun 16 '23 17:06 zanyar3

@distantcam works like a charm

swotiendang avatar May 09 '24 08:05 swotiendang