我们似乎有一个由 Kentico 10 驱动的程序集加载或探测差异(与 9 及更早版本相比),我试图理解,所以我可以解决程序集加载错误,我目前的示例如下......
示例:我们一直在网站中使用专家 PDF 组件 http://www.html-to-pdf.net 该产品有一个托管的 ephtmltopdf.dll 程序集,它依赖于非托管的"帮助程序"DLLepengine.dll也位于 Web 应用程序的 bin/文件夹中,有时在应用程序启动时会引发异常......
在 Kentico 9(及更早版本)下,每当网站启动时,都会引发epengine异常并出现在 Kentico 事件日志中。
在 Kentico 10 下,会发生epengine异常并阻止网站完全运行。
我试图在相同的组件配置下将这两种行为之间的差异相关联。
这是 Kentico 9 及更早版本下的epengineCMS 事件日志条目(不会阻止网站运行):
Event type: Error
Event time: 7/18/2017 4:00:06 AM
Source: Discovery
Event code: E:Kentico_V9CMSbinepengine.dll
User ID: 65
User name: public
Description: Could not load file or assembly 'epengine.dll' or one of its dependencies. The module was expected to contain an assembly manifest.
The file E:Kentico_V9CMSbinepengine.dll is not an assembly or the assembly was compiled for a later version of the .NET runtime.
Machine name: OX
Event URL: /register/all
URL referrer: /Public-(1)/Search-Results
User agent: Mozilla/5.0 (Windows NT 6.1; Trident/7.0; BOIE9;ENUS; rv:11.0) like Gecko
在 Kentico 10 下,这是阻止站点运行的epengine错误。
*** Assembly Binder Log Entry (17/07/2017 @ 4:36:56 PM) ***
The operation failed.
Bind result: hr = 0x80131018. No description available.
Assembly manager loaded from: C:WindowsMicrosoft.NETFrameworkv4.0.30319clr.dll
Running under executable C:WindowsSysWOW64inetsrvw3wp.exe
--- A detailed error log follows.
=== Pre-bind state information ===
LOG: DisplayName = epengine
(Partial)
WRN: Partial binding information was supplied for an assembly:
WRN: Assembly Name: epengine | Domain ID: 2
WRN: A partial bind occurs when only part of the assembly display name is provided.
WRN: This might result in the binder loading an incorrect assembly.
WRN: It is recommended to provide a fully specified textual identity for the assembly,
WRN: that consists of the simple name, version, culture, and public key token.
WRN: See whitepaper http://go.microsoft.com/fwlink/?LinkId=109270 for more information and common solutions to this issue.
LOG: Appbase = file:///C:/inetpub/wwwroot/website/CMS/
LOG: Initial PrivatePath = C:inetpubwwwrootwebsiteCMSbin
LOG: Dynamic Base = C:WindowsMicrosoft.NETFrameworkv4.0.30319Temporary ASP.NET Filesroot672d45d4
LOG: Cache Base = C:WindowsMicrosoft.NETFrameworkv4.0.30319Temporary ASP.NET Filesroot672d45d4
LOG: AppName = f7cc5d08
Calling assembly : (Unknown).
===
LOG: This bind starts in default load context.
LOG: Using application configuration file: C:inetpubwwwrootwebsiteCMSweb.config
LOG: Using host configuration file: C:WindowsMicrosoft.NETFrameworkv4.0.30319aspnet.config
LOG: Using machine configuration file from C:WindowsMicrosoft.NETFrameworkv4.0.30319configmachine.config.
LOG: Policy not being applied to reference at this time (private, custom, partial, or location-based assembly bind).
LOG: Attempting download of new URL file:///C:/Windows/Microsoft.NET/Framework/v4.0.30319/Temporary ASP.NET Files/root/672d45d4/f7cc5d08/epengine.DLL.
LOG: Attempting download of new URL file:///C:/Windows/Microsoft.NET/Framework/v4.0.30319/Temporary ASP.NET Files/root/672d45d4/f7cc5d08/epengine/epengine.DLL.
LOG: Attempting download of new URL file:///C:/inetpub/wwwroot/website/CMS/bin/epengine.DLL.
LOG: Assembly download was successful. Attempting setup of file: C:inetpubwwwrootwebsiteCMSbinepengine.dll
LOG: Entering download cache setup phase.
ERR: Error extracting manifest import from file (hr = 0x80131018).
ERR: Setup failed with hr = 0x80131018.
ERR: Failed to complete setup of assembly (hr = 0x80131018). Probing terminated.
*** Assembly Binder Log Entry (17/07/2017 @ 4:36:56 PM) ***
The operation failed.
Bind result: hr = 0x80131018. No description available.
Assembly manager loaded from: C:WindowsMicrosoft.NETFrameworkv4.0.30319clr.dll
Running under executable C:WindowsSysWOW64inetsrvw3wp.exe
--- A detailed error log follows.
=== Pre-bind state information ===
LOG: DisplayName = epengine
(Partial)
WRN: Partial binding information was supplied for an assembly:
WRN: Assembly Name: epengine | Domain ID: 2
WRN: A partial bind occurs when only part of the assembly display name is provided.
WRN: This might result in the binder loading an incorrect assembly.
WRN: It is recommended to provide a fully specified textual identity for the assembly,
WRN: that consists of the simple name, version, culture, and public key token.
WRN: See whitepaper http://go.microsoft.com/fwlink/?LinkId=109270 for more information and common solutions to this issue.
LOG: Appbase = file:///C:/inetpub/wwwroot/website/CMS/
LOG: Initial PrivatePath = C:inetpubwwwrootwebsiteCMSbin
LOG: Dynamic Base = C:WindowsMicrosoft.NETFrameworkv4.0.30319Temporary ASP.NET Filesroot672d45d4
LOG: Cache Base = C:WindowsMicrosoft.NETFrameworkv4.0.30319Temporary ASP.NET Filesroot672d45d4
LOG: AppName = f7cc5d08
Calling assembly : (Unknown).
===
LOG: This bind starts in default load context.
LOG: Using application configuration file: C:inetpubwwwrootwebsiteCMSweb.config
LOG: Using host configuration file: C:WindowsMicrosoft.NETFrameworkv4.0.30319aspnet.config
LOG: Using machine configuration file from C:WindowsMicrosoft.NETFrameworkv4.0.30319configmachine.config.
LOG: Policy not being applied to reference at this time (private, custom, partial, or location-based assembly bind).
LOG: Attempting download of new URL file:///C:/Windows/Microsoft.NET/Framework/v4.0.30319/Temporary ASP.NET Files/root/672d45d4/f7cc5d08/epengine.DLL.
LOG: Attempting download of new URL file:///C:/Windows/Microsoft.NET/Framework/v4.0.30319/Temporary ASP.NET Files/root/672d45d4/f7cc5d08/epengine/epengine.DLL.
LOG: Attempting download of new URL file:///C:/inetpub/wwwroot/website/CMS/bin/epengine.DLL.
LOG: Assembly download was successful. Attempting setup of file: C:inetpubwwwrootwebsiteCMSbinepengine.dll
LOG: Entering download cache setup phase.
ERR: Error extracting manifest import from file (hr = 0x80131018).
ERR: Setup failed with hr = 0x80131018.
ERR: Failed to complete setup of assembly (hr = 0x80131018). Probing terminated.
每当我在Kentico 9(或更早版本)和10中尝试以下任何操作时,epengine错误总是在Kentico 10中更早出现,阻止网站运行而不是显示在Kentico CMS事件日志中。
- 改用 epengine 的 Nuget 源
- 使用最新版本的 EPENGINE 组件并尝试旧版本(在 Expert 9.0.5 - 11.0 之间)
- 升级/降级 .NET 版本
- 使用相同的应用池设置、.NET 版本、ACL 权限(并更改这些权限进行测试)
- Kentico 10 的全新/基本安装(仍然更早地出现错误)
错误表达式时间的差异似乎是我在 Kentico 9 还是 10 中使用此组件。
我想知道的是,在程序集加载、探测或异常处理方面是否存在差异,这可能有助于解释为什么此组件的错误会阻止 Kentico 10 ASP.NET 网站加载,但不会阻止 Kentico 9 网站使用相同的 IIS 和 .NET 配置加载。
(请注意,我也通过联系供应商来正面解决 PDF 组件错误 - 最终解决方案将是最佳解决方案)。
不理想。此解决方案是解决 ephtmltopdf.dll 和 epengine.dll 程序集在 Web 应用程序启动期间从应用程序的 bin/文件夹加载时引发错误导致 Kentico 10 网站无法加载的问题的解决方法。
此解决方案基于@rocky在原始问题下的评论。
这有效地导致专家PDF组件在Kentico站点已经运行后加载。
并非所有 PDF 生成器的用法都经过测试。此处的代码示例将使用专家 PDF 组件在无法直接引用组件的环境中成功将给定 URL 下载为 PDF 文档。(它适用于我的电脑)
解决方法的步骤-
从应用程序中删除专家 PDF 组件的所有程序集引用;同时删除 C# using 语句。在代码中使用 PDF 类和构造时,您会收到编译错误。
在需要时从箱外部动态加载专家 PDF 程序集(如代码示例中所示 - 请参见 Assembly.LoadFile)。
动态实例化组件(如代码示例所示 - 请参阅动态 + 创建实例)
专家 PDF 代码的其余部分可以保持不变。
// In ~/TestPdf.aspx.cs code-behind page, inside a Kentico 10 website
namespace CMSApp
{
using System;
//using ExpertPdf.HtmlToPdf; // << Namespace no longer available to C# compiler.
using System.Reflection;
public partial class test1 : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
// var converter = new ExpertPdf.HtmlToPdf.PdfConverter(); // << Type no longer available to C# compiler.
// Dynamically load the Expert PDF Assembly, Type and an instance...
Assembly assemb = System.Reflection.Assembly.LoadFile(@"C:KenticoBaseInstallsKentico10.2-appLibMoreExpertPdf-HtmlToPdf-v11.0.0Bin.NET_4.0ephtmltopdf.dll");
dynamic converter = assemb.CreateInstance("ExpertPdf.HtmlToPdf.PdfConverter", true);
// Continue to use old PDF code but without compiler type checks and VS Editor Intellisense.
byte[] pdfBytes = converter.GetPdfBytesFromUrl("https://www.iana.org/domains/reserved");
Response.ClearHeaders();
Response.ContentType = "application/octet-stream";
Response.AppendHeader("Content-Disposition", "attachment; filename=example.pdf");
Response.BinaryWrite(pdfBytes);
Response.Flush();
Response.End();
}
}
}
注意:ExpertPDF 程序集中还有其他结构将失败,您必须像上面的例子一样解决这些结构,例如:
- static UnitsConverter.PixelsToPoints(..)
- HtmlToPdfArea 类
- 图像区域类
- PdfPageSize enum
- 等。
解决方案附录说明
在上面的代码示例中,System.Reflection.Assembly.LoadFile(..)
容易出现不同环境之间的位置问题,或者文件是否被移动。更可靠的替代方法是使用应用程序基子目录来获取程序集,如下所示。请注意,Kentico 10 使用此策略,我们正在搭载他们的 CMS 文件夹结构:
在 ~/CMSDependencies 中创建一个额外的子文件夹,通过在网站中添加专家 PDF DLL(托管和非托管)可以按如下方式探测该子文件夹。你最终会得到这个树结构。
+---CMSDependencies
+---ExpertPdfHtmlToPdf.11.0.0
epengine.dll
ephtmltopdf.dll
将专家 PDF 文件夹的名称添加到 web.config 中探测元素的 privatePath 中,而不使用分号替换任何其他值。
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<probing privatePath="CMSDependenciesNewtonsoft.Json.6.0.0.0;CMSDependenciesExpertPdfHtmlToPdf.11.0.0"/>
</assemblyBinding>
</runtime>
在 C# 中按简单名称加载程序集,如下所示:
Assembly assemb = System.Reflection.Assembly.Load(new AssemblyName("ephtmltopdf"));
根据Kentico 支持的建议,通过将网站热修复到 Kentico 10.0.29(撰写本文时的最高修补程序)解决了该问题。
以下包含通信以供参考。大胆是我对解决方案的强调。
发件人:肯蒂科支持
发送时间:7 月 25-17 日上午
9:46 收件人:约翰·凯恩
主题:RE:专家 PDF 组件与 Kentico 10 不兼容,除非动态加载 票证:0072002734你好约翰,
感谢您的留言。 经过一些调查,此问题可能在Kentico 10 修补程序 10.0.25 中修复。您能否尝试应用最新的修补程序? 该错误与应用程序启动有关,我们的开发人员认为这可能是相关的。
另外,您能否检查所有出现的本机dll引用,包括web.config文件。此注释似乎是相关且准确的 - 无法加载文件或程序集"\bin\ABCpdf8-64.dll"或其依赖项之一。该模块应包含程序集清单
最好的问候,
Juraj Ondrus
Tech.支持领导
我还通过下载 URL 并以编程方式将其转换为 PDF 文档来验证专家 PDF 组件在热固定基础 Kentico 10 安装上正常运行。 (有关代码示例,请参阅专家 PDF 网站和文档。
回购此问题的最快方法
因为我们正处于从 Kentico 从 8.2 升级到 10 的过程中,并解决了自定义代码和自定义组件的多个问题,所以我在这里留下了最简单的存储库场景,它证明了使用专家 PDF 时的问题,以及解决方案,适用于在升级或首次安装期间可能有类似问题的任何其他人。
回购问题
- 使用 Kentico 10 安装程序创建新的网站应用程序。
- 验证网站是否正在运行没有修补程序的 Kentico 10,将报告为 10.0.0。
- 使用 Nuget,引用 ExpertPdfHtmlToPdf 包(版本 9.5 到 11 是我修改的版本)。
- 编译并运行网站 - 网站不会加载,而是显示带有"epengine"消息的 .NET 错误,如问题中发布的那样。
回购解决方案
- 按照 Kentico 修补程序说明将最新的可用修补程序应用于 Kentico 10 安装。
- 验证站点现在报告为 10.0.x,其中 x 是应用的修补程序编号。确保它是>= #25,如 Kentico 支持所提到的。
- 编译并运行网站 - 错误消失,网站正常运行。