我有一个Delphi应用程序,它可以通过在后台打开IE11中的文档并使用默认的PDF打印机打印到PDF来将HTML打印到PDF。这个过程工作得很好。
问题如下:
(例如,我想将5个HTML文档打印为PDF。)
在第一次运行时,它可以很好地处理第一个文档,但会跳过其余文档,并出现以下错误:
在Win Server 2016上:
EOleSysErrorOLE已计划关闭系统。
在Windows 10上:
系统错误OLE错误8150002E
然后我等待"iexploreiderexe"关闭,这需要几秒钟。从那时起,它处理所有文档都很好,无论文档的数量如何。
如果我很长一段时间(大约一天)不使用该应用程序,它的操作与上面相同。
它在第一次运行时跳过,然后等待几秒钟,然后我们就没事了。
我尝试使用OleVariant
和IWebBrowser2
,但结果相同。
我用.Quit
关闭对象。(见下面的代码)。我还尝试了Unassigned
、Free
,在创建新对象之前将对象设置为Null
。它们都不起作用。结果相同。
以下是我作为变通方案尝试的几个方法:
- 如果我不使用
.Quit
,它工作正常,但显然不会关闭任何iexplore.exe。 - 此外,如果我打开一个IE窗口(GUI)并将其最小化,HTML-PDF过程可以正常工作。
- 我还尝试在应用程序启动时调用在
TMainForm.FormCreate()
上创建一个背景IE对象,效果也很好。当应用程序进入HTML-PDF进程时,它会创建一个新的IE背景对象(额外的"iexplore.exe"),并通过保留在FormCreate()
上创建的对象来关闭它。
我想弄清楚为什么它在第一次运行时不能足够快地创建和关闭对象(没有打开IE或没有使用.Quit
)。
下面是代码:
注意:程序也会写一些东西到注册表中,但是为了简单起见,我删掉了一些行(我也可能会在这里或那里删掉一些结尾。注意,除了上面的问题之外,这个函数工作得很好)。
function THTMLMergeDocument.FilePrint: boolean;
var
BrowserObject: OleVariant;
ie : IWebBrowser2;
vaIn, vaOut: OleVariant;
OldHeader, OldFooter, OldPrinterName: String;
OldOrientation: Integer;
Registry : TRegistry;
ST, TOutVal: TDateTime;
sUrl : string;
Flag, TargetFrameName, PostData, Headers : OleVariant;
begin
result := false;
try
if fPrinterName = VTPrint.GetDefaultPrinter then
begin
try
//Tried OleVariant
{
BrowserObject := Unassigned;
BrowserObject := CreateOleObject('InternetExplorer.Application');
BrowserObject.Silent := true;
BrowserObject.Visible := false;
BrowserObject.Navigate('file:\\'+DocumentFileName);
BrowserObject.ExecWB(OLECMDID_PRINT, OLECMDEXECOPT_DONTPROMPTUSER);
while BrowserObject.Busy or BrowserObject.ReadyState <> READYSTATE_COMPLETE do
begin
Application.ProcessMessages;
end;
}
//Tried IWebBrowser2
ie := CoInternetExplorer.Create;
sUrl := 'file:\\'+DocumentFileName;
ie.Navigate(sUrl, Flag, TargetFrameName, PostData, Headers);
ie.ExecWB(OLECMDID_PRINT, OLECMDEXECOPT_DONTPROMPTUSER,vaIn,vaOut);
while ie.ReadyState <> READYSTATE_COMPLETE do
begin
Application.ProcessMessages;
end;
if (PDFOutput) then
begin
ST := Now;
TOutVal := EncodeTime(0,DocumentServerOptions.PDFConverterTimeOutInterval,0,0);
while not PDF.Completed and (Now-ST<TOutVal) do
Application.ProcessMessages;
if PDF.Completed then
result := true
else
WinWordLogProc('ERROR: No response received from PDF converter');
end
else
begin
result := true;
end;
ie.Quit; //close IWebBrowser2 object
BrowserObject.Quit; //close OleVariant object
except on E: Exception do
WinWordLogProc( 'Error class: ' + E.ClassName + #13 + E.Message);
end;
end
else
begin
WinWordLogProc('Error setting default printer to '+fPrinterName);
end;
finally
VTPrint.SetDefaultPrinter(OldPrinterName);
end;
`
我怀疑这与IE对象处理有关,但我不确定,因此在这里寻求帮助。
1条答案
按热度按时间rekjcdws1#
浏览器的
Navigate()
方法是异步的。您应该等待文档加载完成 * 之后 * 才能调用ExecWB()
打印文档,而不是 * 之后 * 调用它。