rdvojmoc / DinkToPdf

C# .NET Core wrapper for wkhtmltopdf library that uses Webkit engine to convert HTML pages to PDF.
MIT License
1.08k stars 414 forks source link

Unable to load DLL 'libwkhtmltox': The specified module could not be found. When using Nuget package #5

Closed graemehyde closed 7 years ago

graemehyde commented 7 years ago

When using the DinkToPdf Nuget package I get the error message below because it is looking for the libwkhtmltox DLL in the same folder the Nuget package DLL is in. For me using VS 2017 on Windows 10 this is:

%UserProfile%\.nuget\packages\dinktopdf\1.0.8\lib\netstandard1.6

When I either manually copy the correct libwkhtmltox DLL to this folder or include the source of the DinkToPdf project into my solution I no longer get this error. By including the project source into my solution the DinkToPdf DLL is then compiled into my output folder where it then also successfully finds the libwkhtmltox DLL.

Is it possible to resolve this issue without having to use the project source or regsvr32.exe? I see that TuesPechkin has an IDeployment interface to address this issue (see: https://github.com/tuespetre/TuesPechkin/issues/57). Is it possible to do something similar in DinkToPdf?

System.AggregateException: One or more errors occurred. (Unable to load DLL 'libwkhtmltox': The specified module could not be found. (Exception from HRESULT: 0x8007007E)) ---> System.DllNotFoundException: Unable to load DLL 'libwkhtmltox': The specified module could not be found. (Exception from HRESULT: 0x8007007E)
   at DinkToPdf.WkHtmlToXBindings.wkhtmltopdf_init(Int32 useGraphics)
   at DinkToPdf.PdfTools.Load() in C:\Users\admin\Documents\DinkToPdf\src\DinkToPdf\PdfTools.cs:line 27
   at DinkToPdf.BasicConverter.Convert(IDocument document) in C:\Users\admin\Documents\DinkToPdf\src\DinkToPdf\BasicConverter.cs:line 42
   at DinkToPdf.SynchronizedConverter.<>n__0(IDocument document)
   at DinkToPdf.SynchronizedConverter.<>c__DisplayClass5_0.<Convert>b__0() in C:\Users\admin\Documents\DinkToPdf\src\DinkToPdf\SynchronizedConverter.cs:line 27
   at System.Threading.Tasks.Task`1.InnerInvoke()
   at System.Threading.Tasks.Task.Execute()
   --- End of inner exception stack trace ---
   at DinkToPdf.SynchronizedConverter.Invoke[TResult](Func`1 delegate) in C:\Users\admin\Documents\DinkToPdf\src\DinkToPdf\SynchronizedConverter.cs:line 51
   at DinkToPdf.SynchronizedConverter.Convert(IDocument document) in C:\Users\admin\Documents\DinkToPdf\src\DinkToPdf\SynchronizedConverter.cs:line 27
graemehyde commented 7 years ago

FYI I tried using this work around to copy the nuget references to the output folder:

<PropertyGroup>
    <TargetFramework>netcoreapp1.1</TargetFramework>
    <CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
  </PropertyGroup>

Source here: https://stackoverflow.com/questions/43837638/how-to-get-net-core-projects-to-copy-nuget-references-to-build-output.

This copies the referenced nuget binaries to the output folder but the .net core web app still uses the dinktopdf.dll located in:

%UserProfile%\.nuget\packages\dinktopdf\1.0.8\lib\netstandard1.6

So unfortunately this doesn't work

rdvojmoc commented 7 years ago

Can you please add this class into your project just to test it before i put in the library?

This is custom assembly load context which can load library from absolute path.

internal class CustomAssemblyLoadContext : AssemblyLoadContext
{
    public IntPtr LoadUnmanagedLibrary(string absolutePath)
    {
        return LoadUnmanagedDll(absolutePath);
    }
    protected override IntPtr LoadUnmanagedDll(String unmanagedDllName)
    {
        return LoadUnmanagedDllFromPath(unmanagedDllName);
    }

    protected override Assembly Load(AssemblyName assemblyName)
    {
        throw new NotImplementedException();
    }
}

Create and call CustomAssemblyLoadContext before you create your converter:

CustomAssemblyLoadContext context = new CustomAssemblyLoadContext();
context.LoadUnmanagedLibrary(path);

var converter = new SynchronizedConverter(new PdfTools());

Tested on Windows 10 64bit and Ubuntu LTS 16.04 64bit.

Will this work for your use case?

graemehyde commented 7 years ago

Thanks!

And yes this works in my case.

arjasepp commented 7 years ago

I have a a bit similar problem. I mean all works on my machine, but when I load my service to Azure. I try to use the html2pdf functionality and it cant load the dll. I see the dll is there and all, but not working. I tried making it build on x86, not yet with x64 as this might be the issue. Will keep you updated.

The message I get is this: An attempt was made to load a program with an incorrect format. (Exception from HRESULT: 0x8007000B)

rdvojmoc commented 7 years ago

Your Azure instance is 64bit or 32bit? Your dev machine is 64bit?

graemehyde commented 7 years ago

arjasepp Azure by default requires the 32 bit version. Check your Application Settings under the App Service your deploying to. See also https://serverfault.com/questions/567987/32bits-or-64bits-for-windows-azure-web-sites.

Unless you're running Windows XP locally your Dev environment will require the 64 bit version which for me created quite a problem when it came to getting our solution to build correctly for Dev and also for our Azure Test and UAT environments.

Because we are using a build server operating on a 64 bit OS I had to add the following to the csproj using DinkToPdf and therefore also using the WkHtmlToPdf library.

  <ItemGroup Condition=" '$(CONFIGURATION)' == 'Debug' And '$(PROCESSOR_ARCHITECTURE)' == 'x86' And '$(PROCESSOR_ARCHITEW6432)' == '' ">
    <ContentWithTargetPath Include="..\..\lib\wkhtmltox\32 bit\libwkhtmltox.dll">
      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
      <TargetPath>libwkhtmltox.dll</TargetPath>
    </ContentWithTargetPath>
  </ItemGroup>

  <ItemGroup Condition=" '$(CONFIGURATION)' == 'Debug' And '$(PROCESSOR_ARCHITECTURE)' == 'AMD64' Or '$(PROCESSOR_ARCHITEW6432)' == 'AMD64' ">
    <ContentWithTargetPath Include="..\..\lib\wkhtmltox\64 bit\libwkhtmltox.dll">
      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
      <TargetPath>libwkhtmltox.dll</TargetPath>
    </ContentWithTargetPath>
  </ItemGroup>

  <ItemGroup Condition=" '$(CONFIGURATION)' == 'Release' ">
    <ContentWithTargetPath Include="..\..\lib\wkhtmltox\32 bit\libwkhtmltox.dll">
      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
      <TargetPath>libwkhtmltox.dll</TargetPath>
    </ContentWithTargetPath>
  </ItemGroup>

I added the WkHtmlToPdf binaries in a "lib\wkhtmltox" folder at the solution level hence the "..\" parent folder traversing at the project level.

arjasepp commented 7 years ago

I got something to work now. Will observe more about this. Thanks @graemehyde

graemehyde commented 7 years ago

arjasepp Just a quick update in case it helps. We've changed tactic with out solution slightly to choose the correct WkHtmlToPdf binary at run time instead of at build time. To do that involves copying all of the WkHtmlToPdf binaries to the output folder (in a sub folder separated by 32 and 64 bit). The correct binary is then determined at run time and then pre-loaded using rdvojmoc's example above with the following additional code:

public static class WkHtmlToPdf
    {
        public static void Preload()
        {
            var wkHtmlToPdfContext = new CustomAssemblyContext();
            var architectureFolder = (IntPtr.Size == 8) ? "64 bit" : "32 bit";
            var wkHtmlToPdfPath = Path.Combine(AppContext.BaseDirectory, $"wkhtmltox\\{architectureFolder}\\libwkhtmltox");

            wkHtmlToPdfContext.LoadUnmanagedLibrary(wkHtmlToPdfPath);
        }
    }

Note no extension (.dll, dylib, or .os) is provided as my understanding is each OS will handle this for you.

My csproj to copy the WkHtmlToPdf binaries to the output folder now looks like this (note no conditions):

  <ItemGroup>
    <ContentWithTargetPath Include="..\..\lib\wkhtmltox\64 bit\libwkhtmltox.dll">
      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
      <TargetPath>wkhtmltox\64 bit\libwkhtmltox.dll</TargetPath>
    </ContentWithTargetPath>
    <ContentWithTargetPath Include="..\..\lib\wkhtmltox\64 bit\libwkhtmltox.dylib">
      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
      <TargetPath>wkhtmltox\64 bit\libwkhtmltox.dylib</TargetPath>
    </ContentWithTargetPath>
    <ContentWithTargetPath Include="..\..\lib\wkhtmltox\64 bit\libwkhtmltox.so">
      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
      <TargetPath>wkhtmltox\64 bit\libwkhtmltox.so</TargetPath>
    </ContentWithTargetPath>
    <ContentWithTargetPath Include="..\..\lib\wkhtmltox\32 bit\libwkhtmltox.dll">
      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
      <TargetPath>wkhtmltox\32 bit\libwkhtmltox.dll</TargetPath>
    </ContentWithTargetPath>
    <ContentWithTargetPath Include="..\..\lib\wkhtmltox\32 bit\libwkhtmltox.dylib">
      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
      <TargetPath>wkhtmltox\32 bit\libwkhtmltox.dylib</TargetPath>
    </ContentWithTargetPath>
    <ContentWithTargetPath Include="..\..\lib\wkhtmltox\32 bit\libwkhtmltox.so">
      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
      <TargetPath>wkhtmltox\32 bit\libwkhtmltox.so</TargetPath>
    </ContentWithTargetPath>
  </ItemGroup>
Stan92 commented 7 years ago

Hi, I tried to follow the @graemehyde post but without success.. I've added a folder named wkhtmltox with 2 subfolders (32 bit & 64 bit) and copied the the respective files.

I get this error System.DllNotFoundException : 'Unable to load DLL 'libwkhtmltox' and a message saying pdftools.cs not found. Does the component support Core 2.0? I use Windows 10.

graemehyde commented 7 years ago

Stan92

Things to check:

1) Does your wkhtmltox folder get copied to the output folder along with the binaries in the correct sub folders when you build? 2) Have you debugged your code to make sure the correct wkhtmltox binary is pre-loaded successfully? If unsuccessful are you paths correct?

I haven't tried with .Net Core 2.0 but the error you're getting suggests to me the problem is not with .Net Core but with one of the two options above.

Stan92 commented 7 years ago

@graemehyde Yes I check the 1st point.. About the 2 point, I think this is point I get a Exception from HRESULT: 0x8007000B (I tried with the 64 bit as well as the 64 bit dll).

JoshLefebvre commented 7 years ago

Also having this problem. Just manually copying the dll into my packages folder for the time being. Any plans on this being fixed in an upcoming release?

rdvojmoc commented 7 years ago

@JoshLefebvre Can you be more specific what do you expect to be fixed?

dragonemp commented 7 years ago

anyone knows where should i put libwkhtmltox.dll in docker container? i have the file in my project, set it to copy always, i can confirm the file exist in docker container in /app and various /bin folders, but when i run app, it's giving the op's error : "Unable to load DLL 'libwkhtmltox': The specified module could not be found. (Exception from HRESULT: 0x8007007E)|| at DinkToPdf.WkHtmlToXBindings.wkhtmltopdf_init(Int32 useGraphics) at DinkToPdf.PdfTools.Load()", i have no idea where to go from here

Kameshwaran commented 7 years ago

Put it in the root directory of the project.

On Sep 14, 2017 9:00 AM, "dragonemp" notifications@github.com wrote:

anyone knows where should i put libwkhtmltox.dll in docker container? i have the file in my project, set it to copy always, i can confirm the file exist in docker container in /app and various /bin folders, but when i run app, it's giving the op's error : "Unable to load DLL 'libwkhtmltox': The specified module could not be found. (Exception from HRESULT: 0x8007007E)|| at DinkToPdf.WkHtmlToXBindings.wkhtmltopdf_init(Int32 useGraphics) at DinkToPdf.PdfTools.Load()", i have no idea where to go from here

— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/rdvojmoc/DinkToPdf/issues/5#issuecomment-329359802, or mute the thread https://github.com/notifications/unsubscribe-auth/AFO-ytN9nIeHJkvMLu9c6NH6sihx6cEaks5siJ3pgaJpZM4OxWKP .

dragonemp commented 7 years ago

I have it in root, still having the issue

On Wed, Sep 13, 2017, 8:49 PM Kameshwaran Sachithanantham < notifications@github.com> wrote:

Put it in the root directory of the project.

On Sep 14, 2017 9:00 AM, "dragonemp" notifications@github.com wrote:

anyone knows where should i put libwkhtmltox.dll in docker container? i have the file in my project, set it to copy always, i can confirm the file exist in docker container in /app and various /bin folders, but when i run app, it's giving the op's error : "Unable to load DLL 'libwkhtmltox': The specified module could not be found. (Exception from HRESULT: 0x8007007E)|| at DinkToPdf.WkHtmlToXBindings.wkhtmltopdf_init(Int32 useGraphics) at DinkToPdf.PdfTools.Load()", i have no idea where to go from here

— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/rdvojmoc/DinkToPdf/issues/5#issuecomment-329359802, or mute the thread < https://github.com/notifications/unsubscribe-auth/AFO-ytN9nIeHJkvMLu9c6NH6sihx6cEaks5siJ3pgaJpZM4OxWKP

.

— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/rdvojmoc/DinkToPdf/issues/5#issuecomment-329362039, or mute the thread https://github.com/notifications/unsubscribe-auth/AUEpxImmxh91jJk1cKR-BGwPT6Wnh4RZks5siKIrgaJpZM4OxWKP .

-- Hai Zhao

rdvojmoc commented 7 years ago

Hello,

If you are using Ubuntu based docker please install libgdiplus. sudo apt-get install libgdiplus

See issue #3 .

dragonemp commented 7 years ago

it's linux docker container but not ubuntu based since sudo is not a recognized command

On Wed, Sep 13, 2017 at 9:32 PM rdvojmoc notifications@github.com wrote:

Hello,

If you are using Ubuntu based docker please install libgdiplus. sudo apt-get install libgdiplus

See issue #3 https://github.com/rdvojmoc/DinkToPdf/issues/3 .

— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/rdvojmoc/DinkToPdf/issues/5#issuecomment-329368260, or mute the thread https://github.com/notifications/unsubscribe-auth/AUEpxMBX3FNdFVuRdHPnWOcdXVxba9G_ks5siKxVgaJpZM4OxWKP .

-- Hai Zhao

dragonemp commented 7 years ago

i began to wonder if it's 32/64 bit issue, where do i find different version of libwkhtmltox dll?

On Wed, Sep 13, 2017 at 9:35 PM Hai Zhao dragonemp@gmail.com wrote:

it's linux docker container but not ubuntu based since sudo is not a recognized command

On Wed, Sep 13, 2017 at 9:32 PM rdvojmoc notifications@github.com wrote:

Hello,

If you are using Ubuntu based docker please install libgdiplus. sudo apt-get install libgdiplus

See issue #3 https://github.com/rdvojmoc/DinkToPdf/issues/3 .

— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/rdvojmoc/DinkToPdf/issues/5#issuecomment-329368260, or mute the thread https://github.com/notifications/unsubscribe-auth/AUEpxMBX3FNdFVuRdHPnWOcdXVxba9G_ks5siKxVgaJpZM4OxWKP .

-- Hai Zhao

-- Hai Zhao

rdvojmoc commented 7 years ago

Which OS is in the docker then?

dragonemp commented 7 years ago

sorry, i'm very new to docker, thought when docker-compose object says "target OS: Linux" , it means linux, but after checking files more closely, i see the image used is microsoft aspnetcore-build 1.1, so this is windows, i checked inside docker container, the dll is definitely there, so this has to be 32 vs 64 issue right? where is the official location to get those dlls?

version: '3'

services: ci-build: image: microsoft/aspnetcore-build:1.0-1.1 volumes:

rdvojmoc commented 7 years ago

It's not 32/64 bit issue. If it was BadImageFormatException is thrown.

rdvojmoc commented 7 years ago

Can I download same docker image that you have to check this myself?

The problem is with one of dependencies that needs to be installed for wkhtmltopdf to work.

dragonemp commented 7 years ago

yeah, that should be public available image, i just use docker run microsoft/aspnetcore-build:1.0-1.1 , and was able to get the image successfully

rdvojmoc commented 7 years ago

Thanks, looking into it.

dragonemp commented 7 years ago

what i'm doing is building a micro service for reporting, in which i generate html (was hoping to use excel, but cannot find anything to convert excel to pdf in .net core), then convert to pdf byte[] as response, it's working fine when i start it in iis express from visual studio, but if i run docker-compose to build it into docker container, i always get cannot load dll issue

rdvojmoc commented 7 years ago

Can you please run command apt-get update and then apt-get install libgdiplus inside docker image?

dragonemp commented 7 years ago

still same issue Unable to load DLL 'libwkhtmltox': The specified module could not be found. (Exception from HRESULT: 0x8007007E)

at DinkToPdf.WkHtmlToXBindings.wkhtmltopdf_init(Int32 useGraphics) at DinkToPdf.PdfTools.Load() at DinkToPdf.BasicConverter.Convert(IDocument document) at Cloud.Services.Reports.BusinessObjects.OshaBO.GeneratePDF(String html, String fileName, PaperKind size) at Cloud.Services.Reports.BusinessObjects.OshaBO.

d__15.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult() at Cloud.Services.Reports.BusinessObjects.OshaBO. d__5.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult() at Cloud.Services.Reports.Controllers.OshasController. d__6.MoveNext()
rdvojmoc commented 7 years ago

Can I see what is getting published to docker image?

dragonemp commented 7 years ago

this is the method to generate pdf, the project is a .net core 1.1 project private byte[] GeneratePDF(string html, string fileName, PaperKind size) { var converter = new BasicConverter(new PdfTools());

        var doc = new HtmlToPdfDocument()
        {
            GlobalSettings = {
                ColorMode = ColorMode.Color,
                Orientation = Orientation.Landscape,
                PaperSize = size,
            },

            Objects = {
                new ObjectSettings() {
                    PagesCount = true,
                    HtmlContent = html,
                    WebSettings = { DefaultEncoding = "utf-8" },
                }
            }
        };
        byte[] pdf = converter.Convert(doc);

if DEBUG

        if (!Directory.Exists("Temp"))
        {
            Directory.CreateDirectory("Temp");
        }
        using (FileStream stream = new FileStream(@"Temp\" + fileName, FileMode.Create))
        {
            stream.Write(pdf, 0, pdf.Length);
        }

endif

        return pdf;
    }
rdvojmoc commented 7 years ago

I meant which files (dlls, etc..) are getting published to Docker image.

dragonemp commented 7 years ago

image

rdvojmoc commented 7 years ago

And how do you run your service (dotnet run...)?

rdvojmoc commented 7 years ago

This is Dockerfile with microsoft/aspnetcore-build:1.0-1.1 image as parent:

FROM microsoft/aspnetcore-build:1.0-1.1

RUN ["apt-get", "update"]
RUN ["apt-get", "-y", "install", "libgdiplus"]

WORKDIR /app

COPY / .

ENTRYPOINT ["dotnet", "DinkToPfd.TestConsoleApp.dll"]

I published DinkToPfd.TestConsoleApp, copied libwkhtmltox.so and libwkhtmltox.dll (they are not published by default) to a publish folder and created docker from it with command sudo docker build -t dinktopdf and then run it with sudo docker run -t dinktopdf

Everything worked as expected.

dragonemp commented 7 years ago

here's my buildDocker.dockerfile FROM microsoft/aspnetcore:1.1.2 RUN apt-get update && apt-get install -y jq && apt-get install -y libgdiplus WORKDIR /app COPY /obj/Docker/publish /app/ COPY /bin/Release/netcoreapp1.1/.xml /app/ COPY /RivoSigning.cer /app/ COPY /libwkhtmltox. /app/ COPY / . EXPOSE 80 HEALTHCHECK --interval=15s --timeout=5s CMD curl -sS http://localhost/health | jq '.status == "Healthy"' || exit 1 ENTRYPOINT ["dotnet", "/app/*****.dll"]

however i'm still getting the issue, I'm so lost right now, not sure what to do to fix it... :(

rdvojmoc commented 7 years ago

Can you paste contents of /app folder?

dragonemp commented 7 years ago

image

dragonemp commented 7 years ago

i'm wondering if i need put the dll into what ever folder dinktopdf installed to, however, i'm not able to find dinktopdf files, can you tell me where it could be?

dragonemp commented 7 years ago

i just tried this code CustomAssemblyLoadContext context = new CustomAssemblyLoadContext(); context.LoadUnmanagedLibrary("/app/libwkhtmltox.dll");

still getting error Unable to load DLL '/app/libwkhtmltox.dll': The specified module could not be found. (Exception from HRESULT: 0x8007007E)|| at System.Runtime.Loader.AssemblyLoadContext.InternalLoadUnmanagedDllFromPath(String unmanagedDllPath) at Cloud.Services.Reports.BusinessObjects.CustomAssemblyLoadContext.LoadUnmanagedDll(String unmanagedDllName) at Cloud.Services.Reports.BusinessObjects.CustomAssemblyLoadContext.LoadUnmanagedLibrary(String absolutePath) at Cloud.Services.Reports.BusinessObjects.OshaBO.GeneratePDF(String html, String fileName, PaperKind size)

i think some dependencies for the dll is missing, but i don't know what is missing :(

rdvojmoc commented 7 years ago

wkhtmltopdf is dependent on this libraries (source)

You can check your docker image if above libraries are installed. I tried with the same docker image as you and after installing libgdiplus everything is working as expected.

What is strange to me are contents of your /app folder. Usually there is no need to have .cs files in your /app folder, only compiled .dlls, configs, etc...

Where is this "/app/*****.dll" from ENTRYPOINT ["dotnet", "/app/*****.dll"]? I can't see it in /app folder?

dragonemp commented 7 years ago

oh, the cs files are copied there due to i started docker from visual studio, it copies everything there i think, i'm new to docker, not familiar with all the settings yet. anyway, i thought the file name doesn't matter, so i replaced it , the actual file is just Cloud.Services.Reports.dll

as of now, the only thing i can think of is i'm using wrong version of the libwkhtmlox.dll since the file is definitely there and all libraries seem to be installed on docker. the thing is i cannot even find a place to download different version of libwkhtmlox.dll anymore, i don't remember where did i get it in the first place, can you let me know how to i find the dll , i still want to try to use 32 and 64 bit dll to test it out

rdvojmoc commented 7 years ago

You can download libwkhtmlox.dll here

dragonemp commented 7 years ago

tried but still error out, i'm wondering if i need copy libwkthmltox to dinktopdf folder in docker image, do you know where's that folder? i'm trying to find it without success

dragonemp commented 7 years ago

By changing to release mode from debug in visual studio, i can successfully convert html to pdf using dinktopdf in .net core microservice. still don't understand why debug build won't work though

OmarMohammad commented 7 years ago

I get the same error and am not sure what I'm doing wrong: "System.DllNotFoundException : Unable to load DLL 'libwkhtmltox': The specified module could not be found. (Exception from HRESULT: 0x8007007E)"

I've placed the libraries at (1) the root (where the csproj is), (2) and several other places, including in the same folder the Nuget package DLL is in. I'm on a 64-bit machine, also tried the 32-bit (but I guess if that was the issue I would get a BadImageFormatException )

pdfexport

timfisher commented 7 years ago

@OmarMohammad Please try the following from above which worked for me:

This is custom assembly load context which can load library from absolute path.

internal class CustomAssemblyLoadContext : AssemblyLoadContext
{
    public IntPtr LoadUnmanagedLibrary(string absolutePath)
    {
        return LoadUnmanagedDll(absolutePath);
    }
    protected override IntPtr LoadUnmanagedDll(String unmanagedDllName)
    {
        return LoadUnmanagedDllFromPath(unmanagedDllName);
    }

    protected override Assembly Load(AssemblyName assemblyName)
    {
        throw new NotImplementedException();
    }
}

Create and call CustomAssemblyLoadContext before you create your converter:

CustomAssemblyLoadContext context = new CustomAssemblyLoadContext();
context.LoadUnmanagedLibrary(path);

Path is the absolute path to the dll (C:/lib.dll)

var converter = new SynchronizedConverter(new PdfTools());

panache62 commented 6 years ago

I have followed timfisher's comments as above but still am unable to load the dll. I am using Visual Studio 2017 Net Core 2.0on a Windows 10 PC. It works fine using the localhost IIS express web server, however, when I publish to the IIS 10 server, it cannot find the 'libwkhtmltox'.dll. I have verified that the files have been copied correctly, and have even tried manual placing of the dll file in every conceivable location.

I guess first up, two questions need answering:

  1. Does it work with Net Core 2.0?
  2. Does it work on IIS 10 (Windows Server 2016)

Could some one please help me here.

Many thanks in advance

timfisher commented 6 years ago

@panache62 I am using this with dotnetcore 2. I feel the readme could be improved a lot, there is no mention that https://wkhtmltopdf.org/downloads.html this is required to be installed on the server. Also direct injection is mandatory otherwise the dll has memory issues when it is re upped.

panache62 commented 6 years ago

Thanks @timfisher, I will give this a go today and let you know if it works

panache62 commented 6 years ago

Hello @timfisher,

Installing wkhtmltopdf on the server resolved the "Unable to load DLL" problem, however, the page now times out with:

"502 - Web server received an invalid response while acting as a gateway or proxy server."

Not sure where to go from here?