1

我已经将 Quartz 设置为 Windows 服务(如果重要,则使用 AdoJobStore)并设法通过远程添加/调度位于我自己的项目 Company.Project 中的自定义 IJob 与 ASP.NET 站点进行通信。服务层。

这花了我一段时间,但只要在 Windows 服务文件夹和网站 bin 文件夹中都存在 Company.Project.ServiceLayer.dll,我的开发机器上一切正常。但是在生产环境中,需要将 Company.Project.ServiceLayer.dll 添加到 GAC。我试图在我的开发机器上模拟这个,从服务文件夹中删除 Company.Project.ServiceLayer.dll 并使用 gacutil 将其添加到 GAC 中。不幸的是,现在当服务启动并尝试实例化我的 IJob 实例时,它无法从 GAC 加载程序集并抛出异常“无法加载文件或程序集”(下面的详细信息)。

我猜 Quartz 在 [QRTZ_JOB_DETAILS].[JOB_CLASS_NAME] 字段中使用反射和 DB 值来尝试加载类?我可能完全错了,但因为这个值(“Company.Product.ServiceLayer.SchedulerJobs.QuintilesEasyJob, Company.Product.ServiceLayer”)只是类的部分描述(它缺少版本和公钥令牌)不是意味着.NET在进行反射时不会查看GAC,因为只有强命名的dll才能存在?这就是我的 GAC 设置现在失败的原因吗?Quartz Windows 服务可以与 GAC 中的 dll 一起使用吗?

非常感谢任何帮助。


2012-10-30 11:20:20,203 [4560] ERROR Topshelf.Model.ServiceCoordinator.OnServiceFault(:0) - Fault on quartz.server: Topshelf.Exceptions.ServiceControlException
Service Start Exception: quartz.server (IQuartzServer)
   at Topshelf.Builders.LocalServiceBuilder`1.StartService(T service)
   at Topshelf.Model.LocalServiceController`1.CallAction[TBefore,TComplete](String text, Action`1 callback, Func`1 before, Func`1 complete)
HelpLink:

Quartz.SchedulerConfigException
Failure occured during job recovery.
   at Quartz.Impl.AdoJobStore.JobStoreSupport.SchedulerStarted() in c:\Work\OpenSource\quartznet\src\Quartz\Impl\AdoJobStore\JobStoreSupport.cs:line 591
   at Quartz.Core.QuartzScheduler.Start() in c:\Work\OpenSource\quartznet\src\Quartz\Core\QuartzScheduler.cs:line 440
   at Quartz.Server.QuartzServer.Start()
   at Topshelf.Builders.LocalServiceBuilder`1.StartService(T service)
HelpLink:

Quartz.JobPersistenceException
Couldn't store trigger 'default.remotelyAddedTrigger' for 'default.remotelyAddedJob' job: Could not load file or assembly 'Company.Product.ServiceLayer' or one of its dependencies. The system cannot find the file specified.
   at Quartz.Impl.AdoJobStore.JobStoreSupport.StoreTrigger(ConnectionAndTransactionHolder conn, IOperableTrigger newTrigger, IJobDetail job, Boolean replaceExisting, String state, Boolean forceState, Boolean recovering) in c:\Work\OpenSource\quartznet\src\Quartz\Impl\AdoJobStore\JobStoreSupport.cs:line 1064
   at Quartz.Impl.AdoJobStore.JobStoreSupport.DoUpdateOfMisfiredTrigger(ConnectionAndTransactionHolder conn, IOperableTrigger trig, Boolean forceState, String newStateIfNotComplete, Boolean recovering) in c:\Work\OpenSource\quartznet\src\Quartz\Impl\AdoJobStore\JobStoreSupport.cs:line 876
   at Quartz.Impl.AdoJobStore.JobStoreSupport.RecoverMisfiredJobs(ConnectionAndTransactionHolder conn, Boolean recovering) in c:\Work\OpenSource\quartznet\src\Quartz\Impl\AdoJobStore\JobStoreSupport.cs:line 814
   at Quartz.Impl.AdoJobStore.JobStoreSupport.RecoverJobs(ConnectionAndTransactionHolder conn) in c:\Work\OpenSource\quartznet\src\Quartz\Impl\AdoJobStore\JobStoreSupport.cs:line 760
   at Quartz.Impl.AdoJobStore.JobStoreSupport.<>c__DisplayClass74.<ExecuteInNonManagedTXLock>b__73(ConnectionAndTransactionHolder conn) in c:\Work\OpenSource\quartznet\src\Quartz\Impl\AdoJobStore\JobStoreSupport.cs:line 3411
   at Quartz.Impl.AdoJobStore.JobStoreSupport.ExecuteInNonManagedTXLock(String lockName, Func`2 txCallback) in c:\Work\OpenSource\quartznet\src\Quartz\Impl\AdoJobStore\JobStoreSupport.cs:line 3481
   at Quartz.Impl.AdoJobStore.JobStoreSupport.SchedulerStarted() in c:\Work\OpenSource\quartznet\src\Quartz\Impl\AdoJobStore\JobStoreSupport.cs:line 581
HelpLink:

System.IO.FileNotFoundException
Could not load file or assembly 'Company.Product.ServiceLayer' or one of its dependencies. The system cannot find the file specified.
   at System.RuntimeTypeHandle.GetTypeByName(String name, Boolean throwOnError, Boolean ignoreCase, Boolean reflectionOnly, StackCrawlMarkHandle stackMark, IntPtr pPrivHostBinder, Boolean loadTypeFromPartialName, ObjectHandleOnStack type)
   at System.RuntimeTypeHandle.GetTypeByName(String name, Boolean throwOnError, Boolean ignoreCase, Boolean reflectionOnly, StackCrawlMark& stackMark, IntPtr pPrivHostBinder, Boolean loadTypeFromPartialName)
   at System.Type.GetType(String typeName, Boolean throwOnError)
   at Quartz.Simpl.SimpleTypeLoadHelper.LoadType(String name) in c:\Work\OpenSource\quartznet\src\Quartz\Simpl\SimpleTypeLoadHelper.cs:line 51
   at Quartz.Impl.AdoJobStore.StdAdoDelegate.SelectJobDetail(ConnectionAndTransactionHolder conn, JobKey jobKey, ITypeLoadHelper loadHelper) in c:\Work\OpenSource\quartznet\src\Quartz\Impl\AdoJobStore\StdAdoDelegate.cs:line 788
   at Quartz.Impl.AdoJobStore.JobStoreSupport.StoreTrigger(ConnectionAndTransactionHolder conn, IOperableTrigger newTrigger, IJobDetail job, Boolean replaceExisting, String state, Boolean forceState, Boolean recovering) in c:\Work\OpenSource\quartznet\src\Quartz\Impl\AdoJobStore\JobStoreSupport.cs:line 1041
4

2 回答 2

1

StdAdoDelegate 上有一个可用的扩展点,方法 GetStorableJobTypeName 可以被覆盖以包含版本和强名称信息。目前没有配置开关来改变行为,因此您需要扩展 SqlServerDelegate(如果使用 SQL Server)。

因此,您的派生类中的新版本将类似于以下内容:

protected override string GetStorableJobTypeName(Type jobType)
{
    return jobType.AssemblyQualifiedName;
}

默认情况下,Quartz 仅使用仅包含类型和程序集名称的程序集限定名称来减少版本控制问题。但请注意它们,当类型中包含版本信息时,如果 dll 版本号发生更改,您需要手动修复数据库数据或创建程序集版本重定向。

于 2012-10-31T05:40:01.080 回答
1

我终于自己搞定了这个。通过将部分名称添加到 app.config 中的完整/强名称映射,我能够让服务在 GAC 中查找,如下所示:

  <runtime>
    <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
      <qualifyAssembly partialName="Company.Product.ServiceLayer" fullName="Company.Product.ServiceLayer, Version=1.0.0.0, Culture=neutral, PublicKeyToken=125c3f237e3350e4"/>
    </assemblyBinding>
  </runtime>
于 2012-10-31T16:44:25.030 回答