Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Closed
graemehyde opened this issue Aug 8, 2017 · 92 comments

Comments

@graemehyde
Copy link

graemehyde commented Aug 8, 2017

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: tuespetre/TuesPechkin#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
Copy link
Author

graemehyde commented Aug 9, 2017

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
Copy link
Owner

rdvojmoc commented Aug 9, 2017

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
Copy link
Author

Thanks!

And yes this works in my case.

@arjasepp
Copy link

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
Copy link
Owner

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

@graemehyde
Copy link
Author

graemehyde commented Aug 14, 2017

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
Copy link

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

@graemehyde
Copy link
Author

graemehyde commented Aug 16, 2017

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
Copy link

Stan92 commented Aug 22, 2017

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
Copy link
Author

graemehyde commented Aug 23, 2017

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
Copy link

Stan92 commented Aug 23, 2017

@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
Copy link

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
Copy link
Owner

rdvojmoc commented Sep 2, 2017

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

@dragonemp
Copy link

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
Copy link

Kameshwaran commented Sep 14, 2017 via email

@dragonemp
Copy link

dragonemp commented Sep 14, 2017 via email

@rdvojmoc
Copy link
Owner

Hello,

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

See issue #3 .

@dragonemp
Copy link

dragonemp commented Sep 14, 2017 via email

@dragonemp
Copy link

dragonemp commented Sep 14, 2017 via email

@rdvojmoc
Copy link
Owner

Which OS is in the docker then?

@dragonemp
Copy link

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:
- .:/src
working_dir: /src
command: /bin/bash -c "dotnet restore ./Cloud.Services.Reports.sln && dotnet publish ./Cloud.Services.Reports.sln -c Release -o ./obj/Docker/publish"

@rdvojmoc
Copy link
Owner

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

@rdvojmoc
Copy link
Owner

rdvojmoc commented Sep 14, 2017

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
Copy link

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
Copy link
Owner

Thanks, looking into it.

@dragonemp
Copy link

dragonemp commented Sep 14, 2017

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
Copy link
Owner

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

@dragonemp
Copy link

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.
<Generate300a_PDF>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.TaskAwaiter1.GetResult() at Cloud.Services.Reports.BusinessObjects.OshaBO. <Generate300a>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.TaskAwaiter1.GetResult()
at Cloud.Services.Reports.Controllers.OshasController.
d__6.MoveNext()

@rdvojmoc
Copy link
Owner

Can I see what is getting published to docker image?

@djsowa
Copy link

djsowa commented Sep 13, 2018

On Linux, this can help:

curl -o /usr/lib/libwkhtmltox.so \
        --location \
        https://github.com/rdvojmoc/DinkToPdf/raw/v1.0.8/v0.12.4/64%20bit/libwkhtmltox.so

@gabrieldevs
Copy link

You need install Mono https://www.mono-project.com/download/stable/

@chadcoley
Copy link

I thought I'd share my result after some time spent on this issue. Quick notes:

  • VS on Mac
  • WebAPI .Net Core 2.1
  • Azure App Service Deployment (32-bit issue)

It all worked independently using the root for storing the DLLs - 64 bit for my local environment and 32 bit for the hosted Azure environment. The CustomAssemblyLoadContext would not work locally and would always give me the "Unable to load DLL 'libwkhtmltox'" message.

After some experimentation, I was able to load my project specifying the extension libwkhtmltox.dylib. However, the convert method would fail as unable to find libwkhtmltox. My suspicion is that dylib extensions must be specified for the VS on mac / web api combo but are left blank in the WkHtmlToXBindings.cs file (line 11).

The hack-fix that ended up working was to leave the 64-bit files in the root and create a post-build event that copied the 32-bit files to the output directory when doing a production build. Here is an example:

cp "${ProjectDir}/lib/32bit/libwkhtmltox.dll" "${TargetDir}"

Now I'm able to run locally and in my hosted environment, although it was a painful to get there. I'm sure there are more elegant solutions but too much time has been spent getting it to work.

I hope this helps someone else.

@ghost
Copy link

ghost commented Nov 5, 2018

The target platform is replaced by X64 or X86.

@chadcoley
Copy link

@rokeyyan If I understand your question correctly, in my setup for the Build Configuration "Release" for the Platform "Any CPU", the post-build action copies the 32-bit versions to the root. The ${TargetDir} looks something like this:

/bin/Release/netcoreapp2.1/

I hope this helps!

@Sayan751
Copy link

Sayan751 commented Nov 7, 2018

Recently I faced the same problem. Maybe this is a really stupid question, but is there any reason why the libwkhtmltox dll and other binaries are not packaged together in the DinkToPdf nuget package?

@kgrosvenor
Copy link

kgrosvenor commented Nov 20, 2018

Doesnt work on mac here either, same error... cant we package the DLL in the library, this is a farce.

@willemmm
Copy link

frustrating to read through all the comments with no resolution - there's obviously an issue with core 2 loading external dll's

@sasusi
Copy link

sasusi commented Jan 13, 2019

I am getting the below error, Unable to load DLL 'libwkhtmltox'. Given below are the configurations

Application is working fine with development server in IIS express. but while deployed in IIS(windows 2012 R2 - .net Core 2.0), application
is throwing the above error in both scenarios.

1)libwkhtmltox(12.4) is copied in the root directory.
2)Even we have tried the option of loading the DLL from the LoadUnmanagedLibrary.. as well.

Please support.

@teokalu
Copy link

teokalu commented Feb 5, 2019

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?

It did in my case, in case anybody is interested :) Thanks so much!

@sasusi
Copy link

sasusi commented Feb 9, 2019

issue was resolved after installing MS visual C++ 2015 redistributable package in the server. Thanks a lot for the support

@tommyannguyen
Copy link

issue was resolved after installing MS visual C++ 2015 redistributable package in the server. Thanks a lot for the support

It's work for me in this case

@BTMutturaj
Copy link

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?

I tried this and its working locally fine for me but when I'm trying to publish in azure I'm getting the following error and the whole application is failing

An error occurred while starting the application.
DllNotFoundException: Unable to load DLL 'D:\home\site\wwwroot\bin\Debug\netcoreapp2.0\libwkhtmltox': The specified module could not be found. (Exception from HRESULT: 0x8007007E)
System.Runtime.Loader.AssemblyLoadContext.InternalLoadUnmanagedDllFromPath(string unmanagedDllPath)

DllNotFoundException: Unable to load DLL 'D:\home\site\wwwroot\bin\Debug\netcoreapp2.0\libwkhtmltox': The specified module could not be found. (Exception from HRESULT: 0x8007007E)
System.Runtime.Loader.AssemblyLoadContext.InternalLoadUnmanagedDllFromPath(string unmanagedDllPath)
System.Runtime.Loader.AssemblyLoadContext.LoadUnmanagedDllFromPath(string unmanagedDllPath)
Socrates.ApiServices.Startup+CustomAssemblyLoadContext.LoadUnmanagedDll(string unmanagedDllName) in Startup.cs
Socrates.ApiServices.Startup.ConfigureServices(IServiceCollection services) in Startup.cs
System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
Microsoft.AspNetCore.Hosting.ConventionBasedStartup.ConfigureServices(IServiceCollection services)
Microsoft.AspNetCore.Hosting.Internal.WebHost.EnsureApplicationServices()
Microsoft.AspNetCore.Hosting.Internal.WebHost.BuildApplication()

@amolhshete
Copy link

its very pain to use this library. I'm getting following exception when I'm deploying with Azure service fabric. So my deployment gets failed when I tried to load unmanaged library. I have tried all the solutions mentioned above.

Can anyone please help me out, I have waste lot of time to get it work.

Description: The process was terminated due to an unhandled exception.
Exception Info: System.DllNotFoundException: Unable to load DLL 'libwkhtmltox' or one of its dependencies: The specified module could not be found. (Exception from HRESULT: 0x8007007E)
at DinkToPdf.WkHtmlToXBindings.wkhtmltopdf_deinit()
at DinkToPdf.PdfTools.Dispose(Boolean disposing)
at DinkToPdf.PdfTools.Finalize()

@joubini
Copy link

joubini commented Jun 12, 2019

I was getting similar unable to load dll issues as above. I had no issues after switching to this fork: https://www.nuget.org/packages/RndUsr0.DinkToPdf/. I found it linked from this discussion: #18.

Hopefully this saves someone time from trying the myriad solutions listed in this thread.

@jcpc91
Copy link

jcpc91 commented Aug 19, 2019

hi thanks for the help
I have some doubts about the realease to productiontion of the desktopapp . how a affects this solutions
true

thnaks
sorry for my english i dont speak

@ABakumenko
Copy link

download this on server, where you try to use libwkhtmltox.dll
https://support.microsoft.com/ru-ru/help/2977003/the-latest-supported-visual-c-downloads

@MarcusBullock
Copy link

why is this issue closed? I can only see some random person's workaround / hack. this is pretty sloppy, having to load an unmanaged DLL.

@dgwaldo
Copy link

dgwaldo commented Jan 4, 2021

why is this issue closed? I can only see some random person's workaround / hack. this is pretty sloppy, having to load an unmanaged DLL.

I'm guessing more people are running into the issue of not having the C++ libs loaded as mentioned by @MarcusBullock . We had this happen and the error is pretty misleading. It worked fine locally and on our development env, but promoting to pre-prod we hit this error.

@ToMakeSense
Copy link

ToMakeSense commented Jan 5, 2021

why is this issue closed? I can only see some random person's workaround / hack. this is pretty sloppy, having to load an unmanaged DLL.

I'm guessing more people are running into the issue of not having the C++ libs loaded as mentioned by @MarcusBullock . We had this happen and the error is pretty misleading. It worked fine locally and on our development env, but promoting to pre-prod we hit this error.

@dgwaldo @MarcusBullock you can use Haukcode.DinkToPdf instead(Nuget), the source repo is https://github.com/HakanL/WkHtmlToPdf-DotNet which is forked from this repo.

@hubert17
Copy link

I was getting similar unable to load dll issues as above. I had no issues after switching to this fork: https://www.nuget.org/packages/RndUsr0.DinkToPdf/. I found it linked from this discussion: #18.

Hopefully this saves someone time from trying the myriad solutions listed in this thread.

This solves the problem about "pdftools.cs not found."
Thank you!

@ahjashish
Copy link

ahjashish commented Aug 17, 2021

I am running the code in Lambda with .net core 3.1 runtime and getting the following error

One or more errors occurred. (Unable to load shared library 'libwkhtmltox' or one of its dependencies. In order to help diagnose loading problems, consider setting the LD_DEBUG environment variable: liblibwkhtmltox: cannot open shared object file: No such file or directory) - StackTrace: at DinkToPdf.SynchronizedConverter.Invoke[TResult](Func1 delegate)

Verified that the files libwkhtmltox.dll and libwkhtmltox.so are part of the final lambda package.

Tried switching from DinkToPdf to RndUsr0.DinkToPdf as mentioned above and it still didn't work, giving the exact same error.

Also tried loading the unmanaged dll using the suggested workaround, everything works perfectly on local, test cases pass. As soon as we package and push to lambda, it fails at runtime.

// .csproj reference used
<None Update="libwkhtmltox.dll">
  <CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Update="libwkhtmltox.so">
  <CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>

// Assembly load code reference used
var context = new AssemblyLoader();
context.LoadUnmanagedLibrary(Directory.GetCurrentDirectory() + "/libwkhtmltox.dll");
_dinkToPdfConverter = new SynchronizedConverter(new PdfTools());

This library is so frustrating to wrap my head around. Even after reading so many comments at multiple places, still doesn't have a clear solution to fix it.

@Limited7247
Copy link

@ahjashish Did you find any solution for this issue?
I got the same issue on AWS Lambda .NET Core 3.1. Same exception message too. :))

@lfrz74
Copy link

lfrz74 commented Feb 14, 2024

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?

I tried this and its working locally fine for me but when I'm trying to publish in azure I'm getting the following error and the whole application is failing

An error occurred while starting the application. DllNotFoundException: Unable to load DLL 'D:\home\site\wwwroot\bin\Debug\netcoreapp2.0\libwkhtmltox': The specified module could not be found. (Exception from HRESULT: 0x8007007E) System.Runtime.Loader.AssemblyLoadContext.InternalLoadUnmanagedDllFromPath(string unmanagedDllPath)

DllNotFoundException: Unable to load DLL 'D:\home\site\wwwroot\bin\Debug\netcoreapp2.0\libwkhtmltox': The specified module could not be found. (Exception from HRESULT: 0x8007007E) System.Runtime.Loader.AssemblyLoadContext.InternalLoadUnmanagedDllFromPath(string unmanagedDllPath) System.Runtime.Loader.AssemblyLoadContext.LoadUnmanagedDllFromPath(string unmanagedDllPath) Socrates.ApiServices.Startup+CustomAssemblyLoadContext.LoadUnmanagedDll(string unmanagedDllName) in Startup.cs Socrates.ApiServices.Startup.ConfigureServices(IServiceCollection services) in Startup.cs System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() Microsoft.AspNetCore.Hosting.ConventionBasedStartup.ConfigureServices(IServiceCollection services) Microsoft.AspNetCore.Hosting.Internal.WebHost.EnsureApplicationServices() Microsoft.AspNetCore.Hosting.Internal.WebHost.BuildApplication()

Thanks it worked

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests