1

我们有我试图理解的由 Kentico 10(与 9 及更早版本相比)驱动的程序集加载或探测差异,因此我可以解决程序集加载错误,我当前的示例如下...

示例:我们一直在来自http://www.html-to-pdf.net的网站中使用 Expert PDF 组件 该产品有一个托管的 ephtmltopdf.dll 程序集,它依赖于非托管的“帮助”DLL epengine.dll也位于旁边在 web 应用程序的 bin/ 文件夹中,有时应用程序启动时会引发异常...

在 Kentico 9(和更早版本)下,每当网站启动时,都会引发epengine异常并出现在 Kentico 事件日志中。

在 Kentico 10 下,发生epengine异常并阻止网站完全运行。

我试图在相同的组件配置下关联这两种行为之间的差异。


这是 Kentico 9 及更早版本下的epengine CMS 事件日志条目(不阻止网站运行):

Event type: Error
Event time: 7/18/2017 4:00:06 AM
Source: Discovery
Event code: E:\Kentico_V9\CMS\bin\epengine.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_V9\CMS\bin\epengine.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:\Windows\Microsoft.NET\Framework\v4.0.30319\clr.dll
Running under executable  C:\Windows\SysWOW64\inetsrv\w3wp.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:\inetpub\wwwroot\website\CMS\bin
LOG: Dynamic Base = C:\Windows\Microsoft.NET\Framework\v4.0.30319\Temporary ASP.NET Files\root\672d45d4
LOG: Cache Base = C:\Windows\Microsoft.NET\Framework\v4.0.30319\Temporary ASP.NET Files\root\672d45d4
LOG: AppName = f7cc5d08
Calling assembly : (Unknown).
===
LOG: This bind starts in default load context.
LOG: Using application configuration file: C:\inetpub\wwwroot\website\CMS\web.config
LOG: Using host configuration file: C:\Windows\Microsoft.NET\Framework\v4.0.30319\aspnet.config
LOG: Using machine configuration file from C:\Windows\Microsoft.NET\Framework\v4.0.30319\config\machine.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:\inetpub\wwwroot\website\CMS\bin\epengine.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:\Windows\Microsoft.NET\Framework\v4.0.30319\clr.dll
Running under executable  C:\Windows\SysWOW64\inetsrv\w3wp.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:\inetpub\wwwroot\website\CMS\bin
LOG: Dynamic Base = C:\Windows\Microsoft.NET\Framework\v4.0.30319\Temporary ASP.NET Files\root\672d45d4
LOG: Cache Base = C:\Windows\Microsoft.NET\Framework\v4.0.30319\Temporary ASP.NET Files\root\672d45d4
LOG: AppName = f7cc5d08
Calling assembly : (Unknown).
===
LOG: This bind starts in default load context.
LOG: Using application configuration file: C:\inetpub\wwwroot\website\CMS\web.config
LOG: Using host configuration file: C:\Windows\Microsoft.NET\Framework\v4.0.30319\aspnet.config
LOG: Using machine configuration file from C:\Windows\Microsoft.NET\Framework\v4.0.30319\config\machine.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:\inetpub\wwwroot\website\CMS\bin\epengine.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 组件错误 - 最终解决方案将是最好的解决方案)。

4

2 回答 2

2

不理想。此解决方案是解决在 Web 应用程序启动期间从应用程序的 bin/ 文件夹加载时 ephtmltopdf.dll 和 epengine.dll 程序集抛出错误导致 Kentico 10 网站无法加载的问题的解决方法。

该解决方案基于@rocky在原始问题下的评论。

这有效地导致 Expert PDF 组件在 Kentico 站点已经运行后加载。

并非 PDF 生成器的所有用法都经过测试。此处的代码示例将在无法直接引用组件的环境中使用 Expert PDF 组件成功将给定 URL 下载为 PDF 文档。(它适用于我的电脑)


解决步骤 -

  1. 从您的应用程序中删除 Expert PDF 组件的所有装配参考;还删除 C# using 语句。在代码中使用 PDF 类和构造时,您会遇到编译错误。

  2. 需要时从 bin 外部动态加载 Expert PDF 程序集(如代码示例中所示 - 请参阅 Assembly.LoadFile)。

  3. 动态实例化组件(如代码示例所示 - 请参阅动态 + CreateInstance )

  4. 您的 Expert 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:\KenticoBaseInstalls\Kentico10.2-app\LibMore\ExpertPdf-HtmlToPdf-v11.0.0\Bin\.NET_4.0\ephtmltopdf.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 程序集中还有其他构造会失败,您必须像上面的示例一样解决这些构造,例如:

  • 静态 UnitsConverter.PixelsToPoints(..)
  • HtmlToPdfArea 类
  • ImageArea 类
  • PdfPageSize 枚举
  • 等等

解决方案的补充说明

在上面的代码示例System.Reflection.Assembly.LoadFile(..)中,不同环境之间或文件移动时容易出现位置问题。更强大的替代方法是使用应用程序基础子目录来获取程序集,如下所示。请注意,Kentico 10 使用了这种策略,我们正在搭载他们的 CMS 文件夹结构:

在 ~/CMSDependencies 中创建一个额外的子文件夹,通过将 Expert PDF DLL(托管和非托管)添加到其中,可以在网站中进行如下探测。你最终会得到这个树形结构。

+---CMSDependencies
    +---ExpertPdfHtmlToPdf.11.0.0
            epengine.dll
            ephtmltopdf.dll

将 Expert Pdf 文件夹的名称添加到 web.config 中探测元素的 privatePath 中,而不使用分号替换任何其他值。

  <runtime>
    <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
      <probing privatePath="CMSDependencies\Newtonsoft.Json.6.0.0.0;CMSDependencies\ExpertPdfHtmlToPdf.11.0.0"/>
    </assemblyBinding>
  </runtime>

通过简单的名称在 C# 中加载程序集,如下所示:

Assembly assemb = System.Reflection.Assembly.Load(new AssemblyName("ephtmltopdf"));
于 2017-07-19T21:48:51.723 回答
0

根据 Kentico Support 的建议,通过将网站修补到 Kentico 10.0.29(撰写本文时的最高修补程序)解决了该问题。

通信包括在下面以供参考。粗体是我对解决方案的强调。

发件人:Kentico Support
发送时间:7 月 25 日 17 日上午 9:46
收件人:John Kane
主题:RE:专家 PDF 组件与 Kentico 10 不兼容,除非动态加载 Ticket:0072002734

你好约翰,

感谢您的留言。经过一些调查,此问题可能已在 Kentico 10 修补程序 10.0.25 中得到修复。您能否尝试应用最新的修补程序?该错误与应用程序启动有关,我们的开发人员认为这可能是相关的。

另外,您能否检查所有出现的本机 dll 引用,包括 web.config 文件。此评论似乎是相关且准确的 -无法加载文件或程序集 '\bin\ABCpdf8-64.dll' 或其依赖项之一。该模块应包含程序集清单

最好的问候,
Juraj Ondrus
Tech。支持铅

我还通过下载 URL 并将其以编程方式将其转换为 PDF 文档,验证了 Expert PDF 组件在经过修补的基本 Kentico 10 安装上正常运行。(有关代码示例,请参阅 Expert PDF 网站和文档。)

回购此问题的最快方法

因为我们正处于从 8.2 到 10 的 Kentico 升级过程中,并解决了自定义代码和自定义组件的多个问题,所以我在这里留下了最简单的 repo 场景,它证明了使用 Expert PDF 时的问题,以及其他任何人的解决方案谁可能在升级或首次安装期间遇到类似问题。

回购问题

  1. 使用 Kentico 10 安装程序创建一个新的网站应用程序。
  2. 验证网站正在运行没有修补程序的 Kentico 10,将报告为 10.0.0。
  3. 使用 Nuget,参考 ExpertPdfHtmlToPdf 包(版本 9.5 到 11 是我修改的版本)。
  4. 编译并运行该网站 - 该网站不会加载,而是显示一个带有“epengine”消息的 .NET 错误,就像问题中发布的那样。

回购解决方案

  1. 按照 Kentico 修补程序说明,​​将最新的可用修补程序应用于 Kentico 10 安装。
  2. 验证站点现在报告为 10.0.x,其中 x 是应用的修补程序编号。确保它 >= #25,正如 Kentico 支持所提到的。
  3. 编译并运行网站 - 错误消失,网站正常运行。
于 2017-07-27T13:52:07.480 回答