Quartz.NET作为GAC中具有依赖关系的Windows服务

时间:2012-10-30 15:46:42

标签: reflection gac quartz.net quartz.net-2.0

我已经将Quartz设置为Windows服务(如果重要的话,使用AdoJobStore)并设法通过远程处理来添加/安排生活在我自己的项目公司中的自定义IJob的ASP.NET站点与之通信.Project.ServiceLayer。

这花了我一段时间但是我的开发机器上的所有工作都正常,前提是Windows服务文件夹和网站bin文件夹中都存在Company.Project.ServiceLayer.dll。但是,在生产环境中,需要将Company.Project.ServiceLayer.dll添加到GAC。我试图在我的开发机器上模拟这个,从services文件夹中删除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进行反射时,.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

2 个答案:

答案 0 :(得分:1)

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

因此,你的派生类中的新版本将会是这样的:

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

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

答案 1 :(得分: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>