可执行文件因奇怪的异常而失败

Jam*_*one 5 .net c# ilmerge quartz.net

我在C#.NET 4.0 Windows服务应用程序中使用ILMerge和Quartz.NET.该应用程序运行良好,而不使用ILMerge,但现在我们即将发布发布,我想将所有DLL组合成一个可执行文件.

问题是,ILMerge似乎工作正常,但是当我运行组合的可执行文件时,它会抛出此异常:

未处理的异常:Quartz.SchedulerException:无法实例化ThreadPool类型"Quartz.Simpl.SimpleThreadPool".---> System.InvalidCastException:无法将类型为"Quartz.Simpl.SimpleThreadPool"的对象强制转换为"Quartz.Spi.IThreadPool".
在Quartz.Util.ObjectUtils.InstantiateType [T](类型型):行0
在Quartz.Impl.StdSchedulerFactory.Instantiate():行0
---内部异常堆栈跟踪---结束
在Quartz.Impl. StdSchedulerFactory.Instantiate()in:
在Quartz.Impl.StdSchedulerFactory.GetScheduler()中的第0行:第0行

有谁知道为什么会这样?我已经浪费了4个多小时,我无法弄明白.如果我不与ILMerge结合,那么一切运行正常(Quartz.dll和Common.Logging.dll位于同一目录中).

我敢肯定有人必须尝试过像这样包装Quartz.net,任何想法吗?

Mil*_*ski 1

免责声明:尽管我花了一些时间与 ILMerge 作斗争,但我根本不了解 Quartz.NET。当我最终了解它的局限性时......我停止使用它。

ILMerge 的应用程序往往会对包含“反射”一词的所有内容产生问题。我可以猜测(我从未使用过 Quartz.NET)某些类是使用反射解析并由配置文件驱动的。

类不仅通过其名称(带有命名空间)进行标识,还通过其来源的程序集进行标识(不幸的是,它不会显示在异常消息中)。因此,我们假设您(在 ILMerging 之前)有两个程序集 A(用于您的应用程序)和 Q(用于 Quartz.NET)。程序集“A”引用程序集“Q”,并使用实现“Q:QIntf”的类“Q:QClass”。合并后,这些类变成“A:QClass”和“A:QIntf”(它们从程序集 Q 移动到 A),并且代码中的所有引用都已被替换为使用这些(完全)新的类/接口,因此“A :QClass”现在正在实现“A:QIntf”。但是,它没有更改任何可能仍引用“Q:QClass”的配置文件/嵌入字符串。

因此,当应用程序读取那些未更新的配置文件时,它仍然加载“Q:QClass”(为什么它可以找到它是一个不同的问题,也许您将程序集“Q”留在当前文件夹中,或者也许它在GAC中 - 请参阅1) 。无论如何,“Q:QClass”不实现“A:QIntf”,它仍然实现“Q:QIntf”,即使它们是二进制相同的 - 所以你不能将“Q:QClass”转换为“A:QIntf”。

不理想但可行的解决方案是“嵌入”程序集而不是“合并”它们。我编写了一个开源工具来执行此操作(嵌入而不是合并),但它与这个问题无关。因此,如果您决定嵌入,请询问我。

  1. 您可以通过删除(隐藏,无论对您有用的任何内容)PC 上的每个 Q.dll 实例来测试它。如果我是对的,异常现在应该是“FileNotFound”。