Comments (25)
What were you passing in before?
from tuespechkin.
new StaticDeployment(HttpRuntime.AppDomainAppPath + "/wkhtml"))
from tuespechkin.
Any better solution? Not sure why I need a brand new copy each time.
from tuespechkin.
Wait a minute -- you are using the RemotingToolset
, right?
from tuespechkin.
static string tpath = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString(), "wkhtml");
private static IConverter pdfConverter = new ThreadSafeConverter(new RemotingToolset<PdfToolset>(new Win32EmbeddedDeployment(new StaticDeployment(tpath))));
from tuespechkin.
I've been able to reproduce the issue and correct it. I'll release a patch version tonight.
The issue was only surfacing when converting from URL instead of just raw HTML; when the AppDomain unloads the RemotingConverter
was not invoking wkhtmltopdf_deinit
which must have left some unmanaged web loading object hanging before trying to unload the AppDomain. The temporary workaround is a bit hacky but it stays underneath the surface of the public API. There will now be a unit test for this scenario as well -- converting from URL after AppDomain unloading.
from tuespechkin.
Thanks a lot.
from tuespechkin.
I tried the new changes, and the file is still locked when I try to check-in new changes on TFS, but fortunately when the build crashes, I simply restart it and it works fine.
from tuespechkin.
If you had an existing one running with the unpatched version, that would probably happen.
- Derek Gray
On Jan 6, 2015, at 12:04 PM, timdooling [email protected] wrote:
I tried the new changes, and the file is still locked when I try to check-in new changes on TFS, but fortunately when the build crashes, I simply restart it and it works fine.
—
Reply to this email directly or view it on GitHub.
from tuespechkin.
I have a similar issue with the latest version (v2.0.1). I am calling convert from two IIS hosted web applications (vb.net Web Forms).
My environment:
• One AppPool
• Two web sites running from different folders but having the same code and AppPool (it is a custom CMS)
• TuesPechkin wrapped in a class (acting as a thin wrapper) and included as a reference in the web application projects (using TuesPechkin.Wkhtmltox.Win64 too)
The pdfs are generated from a URL. Trying to generate a pdf from one of the two sites works (no matter which site or how many times in a row). After the first generation though, any attempt to generate a pdf from the other site completely locks the AppPool (requires killing the process).
Converter is a static (shared in vb.net) field. I am using IIS 8.5 with a 64 bit AppPool (Enable 32-Bit Applications = False). This is how I create the converter:
Converter = New ThreadSafeConverter(
New RemotingToolset(Of PdfToolset)(
New Win64EmbeddedDeployment(
New StaticDeployment(
Path.Combine(Path.GetTempPath(), "mycustomcms")
)
)
)
)
ANOTHER THING...
...is that the wkhtmltox dll is not copied in the temp folder (and mycustomcms is not created either).
--Matteo
from tuespechkin.
If you must have both sites in one app pool (ie one process) then each site will need to point to a unique deployment of wkhtmltox.dll.
- Derek Gray
On Jan 16, 2015, at 9:18 AM, wc-matteo [email protected] wrote:
I have a similar issue with the latest version (v2.0.1). I am calling convert from two IIS hosted web applications (vb.net Web Forms).
My environment:
• One AppPool
• Two web sites running from different folders but having the same code and AppPool (it is a custom CMS)
• TuesPechkin wrapped in a class (acting as a thin wrapper) and included as a reference in the web application projects (using TuesPechkin.Wkhtmltox.Win64 too)The pdfs are generated from a URL. Trying to generate a pdf from one of the two sites works (no matter which site or how many times in a row). After the first generation though, any attempt to generate a pdf from the other site completely locks the AppPool (requires killing the process).
Converter is a static (shared in vb.net) field. I am using IIS 8.5 with a 64 bit AppPool (Enable 32-Bit Applications = False). This is how I create the converter:
Converter = New ThreadSafeConverter(
New RemotingToolset(Of PdfToolset)(
New Win64EmbeddedDeployment(
New StaticDeployment(
Path.Combine(Path.GetTempPath(), "mycustomcms")
)
)
)
)Matteo
—
Reply to this email directly or view it on GitHub.
from tuespechkin.
And giving the StaticDeployment constructor a path with a random string (or a guid) in it could accomplish that (removing the static modifier)? The issue that the dll doesn't get copied in the temp folder remains however... it is copied over in the web applications bin folder though (TuesPechkin.Wkhtmltox.Win64.dll)
from tuespechkin.
The temp folder will vary by the user your app pool runs under, so be sure you are checking the right one. It could be C:\Windows\Temp
or C:\Users\<some_user_name>\AppData\Local\Temp
depending on how you have things set up.
With 2.1.0 there will be an included TempFolderDeployment
class that somewhat imitates the deployment behavior of 1.0.3. I would recommend switching to use that as soon as 2.1.0 is released. You can use the same method right now if you want, it pretty much does this:
Path = System.IO.Path.Combine(
System.IO.Path.GetTempPath(),
AppDomain.CurrentDomain.BaseDirectory.GetHashCode().ToString());
Assuming each of your sites have different base directories, that should work for you.
from tuespechkin.
>The temp folder will vary by the user your app pool runs under
Duh... so obvious! -_-
Now it's working, but after having generated at least one pdf from each site, it hangs. It must be that static modifier.
Is there a really good reason not to want to instantiate the converter multiple times? I mean, is it a matter of performance or...? And do you have any advice for a .net facility that persist data per site (and not per AppPool as the static modifier does)?
from tuespechkin.
The reason we don't want to instantiate a converter multiple times is because to do so, we would have to load a unique copy of wkhtmltox.dll into memory for each one. This is due to the nature of unmanaged libraries.
Now, an application pool is a process, so by having multiple sites on one pool, they share that process. That means a single unique wkhtmltox.dll file would be loaded only one time for the process. However, each site will run within its own AppDomain, meaning that your static variable in managed code is not the going to share the same reference between your sites.
So long story short, did you change it to use a random path or the base directory-scope solution I posted above? As long as each site touches a unique copy of the wkhtmltox.dll file, everything should be alright.
from tuespechkin.
I am using the converter in a web service run on IIS.
What I have done is placed a complete, unzipped copy of the "Wkhtmltox.dll" file at the root directory of my web service, and I branch off that to the .dll file using:
Shared Property converter As IConverter = Nothing
...
Dim physicalApplicationPath As String = MyClass.Context.Request.PhysicalApplicationPath
If IsNothing(converter) Then
converter = New ThreadSafeConverter(
New RemotingToolset(Of PdfToolset)(
New StaticDeployment(physicalApplicationPath)))
End If
...
converter = Nothing ' releases the memory to garbage collection
This approach generates pdfs without hanging every time.
The only problem I have is that TFS build fails and I have to retry it when I check in code changes, a minor annoyance, because the file is locked. The first build attempt apparently unlocks it.
I surround my calls to the web service print routine with Using (service) ... End Using.
Apparently between calls the "Wkhtmltox.dll" file is locked, but that doesn't seem to affect whether the system can use it using the method I am using.
I pass a url to the routines to let .NET do all the rendering so I don't have to reinvent the Render subroutine.
I get back a WYSIWYG response as long as I don't have any rendering that depends on javascript.
from tuespechkin.
Sorry for the delayed response.
>each site will run within its own AppDomain
Ah! I was conflating AppPools and AppDomains; now I see...
In my last response I was using your base directory-scope solution. Now I don't seem to be able to get the other site working, not even for one generation (after the other site generation)... I'm back where I started...
This is the converter, as of now:
Converter = New ThreadSafeConverter(
New RemotingToolset(Of PdfToolset)(
New Win64EmbeddedDeployment(
New StaticDeployment(
Path.Combine(
Path.GetTempPath(),
AppDomain.CurrentDomain.BaseDirectory.GetHashCode().ToString())))))
I have checked the temp folder (it's the Windows one, by the way) and the converter successfully creates a directory for each site.
UPDATE
I tried with a simple generic handler (both with iis express and iis). The first generation always succeeds. Every other generation stalls the worker process, which requires to be killed.
Am I doing something wrong?
Nuget packages:
- TuesPechkin 2.0.1
- TuesPechkin.Wkhtmltox.Win64 0.12.1
Imports TuesPechkin
Imports System.IO
Public Class Handler1
Implements System.Web.IHttpHandler
Private Shared Converter As IConverter
Sub ProcessRequest(ByVal context As HttpContext) Implements IHttpHandler.ProcessRequest
If context.Request.QueryString.Item("url") = Nothing Then Exit Sub
context.Response.ContentType = "application/pdf"
Dim Document As New HtmlToPdfDocument
Document.Objects.Add(New ObjectSettings With {
.PageUrl = context.Request.QueryString.Item("url")
})
Converter = New ThreadSafeConverter(
New RemotingToolset(Of PdfToolset)(
New Win64EmbeddedDeployment(
New StaticDeployment(
Path.Combine(
Path.GetTempPath(),
AppDomain.CurrentDomain.BaseDirectory.GetHashCode().ToString())))))
Dim Stream As New MemoryStream(Converter.Convert(Document))
Stream.WriteTo(context.Response.OutputStream)
End Sub
ReadOnly Property IsReusable() As Boolean Implements IHttpHandler.IsReusable
Get
Return False
End Get
End Property
End Class
from tuespechkin.
My apologies @wc-matteo, it does appear that there are some issues when using multiple wkhtmltox.dll files in a single process, and I think it's going to be related to how P/Invoke binds to the native modules.
Looks like I need to start planning for 2.2.0 -- deprecating the WkhtmltoxBindings class and beginning to use dynamically obtained unmanaged delegates. Fun!
from tuespechkin.
Dynamically obtained unmanaged delegates do sound like fun! (whatever they are :P)
But, correct me if I'm wrong, in the generic handler case you're not really using multiple wkhtmltox.dll, are you?
And talking about the generic handler, version 2.1.0 does not work (didn't test with the cms):
[DllNotFoundException: Unable to load DLL 'wkhtmltox.dll': The specified module could not be found. (Exception from HRESULT: 0x8007007E).]
TuesPechkin.ThreadSafeConverter.Invoke(FuncShim`1 delegate) +246
from tuespechkin.
Sorry, I suppose I did not look at your code sample closely enough. You are instantiating a new instance of the converter with each request (in the ProcessRequest method.) You will want to surround that with either a null check, or move that to a static constructor, or if you can in VB.NET, declare it inline with your static field.
from tuespechkin.
Well, you learn something new every day... I thought the compiler automatically did the null check for me with a static field...
It still can't find the dll, though. Can you reproduce it or should I check more thoroughly on my end?
P.s. Could you give me an example of an inline declaration (using C#)?
UPDATE
I can confirm that just updating from 2.0.1 to 2.1.0 generates the error above (tried both with StaticDeployment and the new TempFolderDeployment).
from tuespechkin.
I've just pushed 2.1.1 which address the issue you've discovered.
from tuespechkin.
Thank you for the promptly fix! :)
For a resolution to my original issue I need to wait for 2.2.0 then?
About the TempFolderDeployment: If it copys the dll always in the same folder (per site), when there's a software update to the package, you need to clear the dll from the temp folder, right?
from tuespechkin.
I've actually got the assembly version in the path of the embedded deployment since 2.1.1/0.12.2.1, so you shouldn't have to worry about manually deleting anything.
from tuespechkin.
I have the same issue. I just get the latest version TuesPechkin 2.1.1.0 and TuesPechkin.Wkhtmltox.Win32.dll 0.12.2.1. It works very good on converting html to pdf. The only issue is every time the aspx or aspx.vb file changed and cause recompile, we have to recycle the application pool, otherwise the whole site will freeze.
My environment is a simple web site, just aspx file and aspx.vb file. For testing it only has one page,
I tried all different ways, like, TempFolderDeployment, StaticDeployment, see code below
Public Shared ReadOnly Property convertidor() As IConverter
Get
If _converter Is Nothing Then
SyncLock _PadLock
If _converter Is Nothing Then
'Dim wkhtmltoxPath As String = "C:\Windows\Temp\80570420\4\0.12.2.1"
'Dim physicalApplicationPath As String = "C:\inetpub\wwwroot\MySiteRoot"
_converter = New ThreadSafeConverter(New RemotingToolset(Of PdfToolset)(New Win32EmbeddedDeployment(New TempFolderDeployment())))
'_converter = New ThreadSafeConverter(New RemotingToolset(Of PdfToolset)(New Win32EmbeddedDeployment(New StaticDeployment(physicalApplicationPath))))
End If
End SyncLock
End If
Return _converter
End Get
End Property
Any idea to get rid of the recycle application pool when code changes.
Thank you,
Gary
from tuespechkin.
Related Issues (20)
- Crashing when second request comes in/ hanging randonmly HOT 1
- SVG text with rounded stroke HOT 3
- Type 'Win32EmbeddedDeployment' is not defined HOT 2
- Tuespechkin generating blank PDF
- IIS wkhtmltox.dll_unload error HOT 2
- Tuespechkin takes a long time to respond, and returns null HOT 2
- TOC produces blank page on second conversion within lifecycle
- Qt: Could not initialize OLE (error 80010106) HOT 2
- System.DllNotFoundException - Unable to load DLL 'wkhtmltox.dll': Access is denied HOT 6
- Can I generate same pdf page height with the HTML page height?
- Could we directly send html content to head/foot, not a html page?
- Tagged Content Failed HOT 1
- Migrate Net Core
- Header ends up outside paper HOT 1
- First time works fine, second request nothing happen HOT 1
- Error in MVC solutions using NuGet package
- Border thickness issue for all elements
- PDF Margin being ignored
- Lib causing 2 versions of razor to happen
- Canvas is not converted to image in pdf
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from tuespechkin.