Closed graemehyde closed 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
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?
Thanks!
And yes this works in my case.
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)
Your Azure instance is 64bit or 32bit? Your dev machine is 64bit?
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.
I got something to work now. Will observe more about this. Thanks @graemehyde
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>
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.
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.
@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).
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?
@JoshLefebvre Can you be more specific what do you expect to be fixed?
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
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 .
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
Hello,
If you are using Ubuntu based docker please install libgdiplus.
sudo apt-get install libgdiplus
See issue #3 .
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
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
Which OS is in the docker then?
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:
It's not 32/64 bit issue. If it was BadImageFormatException is thrown.
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.
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
Thanks, looking into it.
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
Can you please run command apt-get update
and then apt-get install libgdiplus
inside docker image?
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.
Can I see what is getting published to docker image?
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 (!Directory.Exists("Temp"))
{
Directory.CreateDirectory("Temp");
}
using (FileStream stream = new FileStream(@"Temp\" + fileName, FileMode.Create))
{
stream.Write(pdf, 0, pdf.Length);
}
return pdf;
}
I meant which files (dlls, etc..) are getting published to Docker image.
And how do you run your service (dotnet run...)?
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.
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... :(
Can you paste contents of /app folder?
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?
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 :(
wkhtmltopdf is dependent on this libraries (source)
zlib
fontconfig
freetype
libX11
libXext,
libXrender
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?
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
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
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
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 )
@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());
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:
Could some one please help me here.
Many thanks in advance
@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.
Thanks @timfisher, I will give this a go today and let you know if it works
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?
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?