目标
好的,所以我的目标是在我的aspnetboilerplate Web应用程序旁边运行一个Windows服务。 Windows服务的原因是它将从完全独立的虚拟服务器运行Hangfire后台作业。
配置
仅供参考,一切都来自网络应用程序。
这是服务程序文件(我正在使用Topshelf,但我认为这并不重要)。
HostFactory.Run(x =>
{
x.Service<PortalService>(sc =>
{
sc.ConstructUsing(() => new PortalService());
sc.WhenStarted((tc, hostControl) => tc.Start(hostControl));
sc.WhenStopped((tc, hostControl) => tc.Stop(hostControl));
});
x.UseLog4Net();
x.RunAsLocalSystem();
x.SetServiceName(PortalService.ServiceName);
x.SetDisplayName(PortalService.ServiceDisplayName);
x.SetDescription(PortalService.ServiceDescription);
x.StartAutomatically();
});
这是服务模块
[DependsOn(typeof(PortalCoreModule), typeof(PortalEntityFrameworkModule), typeof(PortalApplicationModule), typeof(AbpHangfireModule))]
public class PortalServiceModule : AbpModule
{
public override void Initialize()
{
IocManager.RegisterAssemblyByConvention(typeof(PortalServiceModule).GetAssembly());
}
public override void PreInitialize()
{
Configuration.BackgroundJobs.UseHangfire(config =>
{
config.GlobalConfiguration.UseSqlServerStorage(PortalConsts.ConnectionStringName, new SqlServerStorageOptions
{
PrepareSchemaIfNecessary = true
});
config.Server = new BackgroundJobServer(new BackgroundJobServerOptions
{
Queues = new[] {BackgroundJobQueueNames.Critical, BackgroundJobQueueNames.Autotask, BackgroundJobQueueNames.Default}
});
config.GlobalConfiguration.UseConsole();
});
GlobalJobFilters.Filters.Add(new DisableMultipleQueuedItemsFilter());
}
}
然后这是我的服务代码
public class PortalService : ServiceControl
{
public const string ServiceName = "PortalWorker";
public const string ServiceDisplayName = "Portal Worker";
public const string ServiceDescription = "Process the background jobs for the Portal.";
private AbpBootstrapper _bootstrapper;
public bool Start(HostControl hostControl)
{
_bootstrapper = AbpBootstrapper.Create<PortalServiceModule>();
_bootstrapper.IocManager
.IocContainer
.AddFacility<LoggingFacility>(f => f.UseAbpLog4Net().WithConfig("log4net.config"));
_bootstrapper.Initialize();
return true;
}
public bool Stop(HostControl hostControl)
{
_bootstrapper.Dispose();
return true;
}
}
然而,每次我运行该服务时,都会出现以下异常
Castle.MicroKernel.ComponentNotFoundException:&#39;没有找到支持服务Portal.BackupMonitoring.IBackupMonitoringManager的组件&#39;
但是,如果我要运行Web应用程序,它工作正常,所以对我来说这不是IBackupMonitoringManager的问题。它必须与服务无法针对DI进行注册有关。
我在这个回购中查看了https://github.com/aspnetboilerplate/aspnetboilerplate-samples
的例子但是这些示例要么已大量过时,要么我看不到带有网络核心Web应用程序的控制台应用程序的示例。
任何有关如何开始这方面的帮助将不胜感激。
这是作业尝试执行时的新异常。
Castle.MicroKernel.Handlers.HandlerException:&#39;无法创建组件 &#39; Portal.Authorization.Users.UserManager&#39;因为它有依赖性 满意。
&#39; Portal.Authorization.Users.UserManager&#39;正在等待以下 依赖关系: - 服务&#39; Portal.Authorization.Roles.RoleManager&#39;已注册,但也在等待依赖。 &#39; Portal.Authorization.Roles.RoleManager&#39;正在等待以下 依赖关系: - Service&#39; System.Collections.Generic.IEnumerable
1[[Microsoft.AspNetCore.Identity.IRoleValidator
1 [[Portal.Authorization.Roles.Role, Portal.Core,Version = 1.0.0.0,Culture = neutral,PublicKeyToken = null]], Microsoft.Extensions.Identity.Core,Version = 2.0.1.0,Culture = neutral, 公钥= adb9793829ddae60]]&#39;没有注册。 - 服务&#39; Microsoft.AspNetCore.Identity.ILookupNormalizer&#39;没有注册。 - 服务&#39; Microsoft.AspNetCore.Identity.IdentityErrorDescriber&#39;没有注册。 - Service&#39; Microsoft.Extensions.Logging.ILogger1[[Abp.Authorization.Roles.AbpRoleManager
2 [[Portal.Authorization.Roles.Role, Portal.Core,Version = 1.0.0.0,Culture = neutral, PublicKeyToken = null],[Portal.Authorization.Users.User,Portal.Core, Version = 1.0.0.0,Culture = neutral,PublicKeyToken = null]],Abp.ZeroCore, Version = 3.2.4.0,Culture = neutral,PublicKeyToken = null]]&#39;哪不是 注册。 - 服务&#39; Microsoft.Extensions.Options.IOptions1[[Microsoft.AspNetCore.Identity.IdentityOptions, Microsoft.Extensions.Identity.Core, Version=2.0.1.0, Culture=neutral, PublicKeyToken=adb9793829ddae60]]' which was not registered. - Service 'Microsoft.AspNetCore.Identity.IPasswordHasher
1 [[Portal.Authorization.Users.User, Portal.Core,Version = 1.0.0.0,Culture = neutral,PublicKeyToken = null]]&#39; 没有注册。 - Service&#39; System.Collections.Generic.IEnumerable1[[Microsoft.AspNetCore.Identity.IUserValidator
1 [[Portal.Authorization.Users.User, Portal.Core,Version = 1.0.0.0,Culture = neutral,PublicKeyToken = null]], Microsoft.Extensions.Identity.Core,Version = 2.0.1.0,Culture = neutral, 公钥= adb9793829ddae60]]&#39;没有注册。 - Service&#39; System.Collections.Generic.IEnumerable1[[Microsoft.AspNetCore.Identity.IPasswordValidator
1 [[Portal.Authorization.Users.User, Portal.Core,Version = 1.0.0.0,Culture = neutral,PublicKeyToken = null]], Microsoft.Extensions.Identity.Core,Version = 2.0.1.0,Culture = neutral, 公钥= adb9793829ddae60]]&#39;没有注册。 - 服务&#39; Microsoft.AspNetCore.Identity.ILookupNormalizer&#39;没有注册。 - 服务&#39; Microsoft.AspNetCore.Identity.IdentityErrorDescriber&#39;没有注册。 - Service&#39; System.IServiceProvider&#39;没有注册。 - Service&#39; Microsoft.Extensions.Logging.ILogger1[[Microsoft.AspNetCore.Identity.UserManager
1 [[Portal.Authorization.Users.User, Portal.Core,Version = 1.0.0.0,Culture = neutral,PublicKeyToken = null]], Microsoft.Extensions.Identity.Core,Version = 2.0.1.0,Culture = neutral, 公钥= adb9793829ddae60]]&#39;没有注册。 &#39;
答案 0 :(得分:1)
我想我现在已经有了这个,所以我将把它作为答案发布,但是如果有任何问题请告诉我。
首先,我必须安装Abp.AspNetCore包。这允许访问IServiceCollection.AddAbp()
扩展方法。
所以我的Program.cs
改为此
static void Main(string[] args)
{
Clock.Provider = ClockProviders.Utc;
var services = new ServiceCollection();
IdentityRegistrar.Register(services);
services.AddAbp<PortalServiceModule>(options =>
{
//Configure Log4Net logging
options.IocManager.IocContainer.AddFacility<LoggingFacility>(
f => f.UseAbpLog4Net().WithConfig("log4net.config")
);
});
HostFactory.Run(x =>
{
x.Service<PortalService>(sc =>
{
sc.ConstructUsing(() => new PortalService());
sc.WhenStarted((tc, hostControl) => tc.Start(hostControl));
sc.WhenStopped((tc, hostControl) => tc.Stop(hostControl));
});
x.UseLog4Net();
x.RunAsLocalSystem();
x.SetServiceName(PortalService.ServiceName);
x.SetDisplayName(PortalService.ServiceDisplayName);
x.SetDescription(PortalService.ServiceDescription);
x.StartAutomatically();
});
}
我在PortalServiceModule上遇到了一些问题。自动化配置已经在PortalApplicationModule中,因此我可能需要重新访问它以删除重复的代码。目前,这就是我的工作。
[DependsOn(typeof(PortalCoreModule), typeof(PortalEntityFrameworkModule), typeof(PortalApplicationModule), typeof(AbpHangfireModule), typeof(AbpZeroCoreModule), typeof(AbpAutoMapperModule))]
public class PortalServiceModule : AbpModule
{
public override void Initialize()
{
IocManager.RegisterAssemblyByConvention(typeof(PortalServiceModule).GetAssembly());
Configuration.Modules.AbpAutoMapper().Configurators.Add(cfg =>
{
cfg.CreateMap<object, int?>().ConvertUsing<NullableIntTypeConverter>();
// Scan the assembly for classes which inherit from AutoMapper.Profile
cfg.AddProfiles(typeof(PortalApplicationModule).GetAssembly());
});
Configuration.BackgroundJobs.UseHangfire(config =>
{
config.GlobalConfiguration.UseSqlServerStorage(PortalConsts.ConnectionStringName, new SqlServerStorageOptions
{
PrepareSchemaIfNecessary = true
});
config.Server = new BackgroundJobServer(new BackgroundJobServerOptions
{
Queues = new[] { BackgroundJobQueueNames.Critical, BackgroundJobQueueNames.Autotask, BackgroundJobQueueNames.Default }
});
config.GlobalConfiguration.UseConsole();
});
GlobalJobFilters.Filters.Add(new DisableMultipleQueuedItemsFilter());
}
public override void PostInitialize()
{
HangfireJobsConfigurer.Configure();
}
}
然后我的实际服务代码变成了这个
public class PortalService : ServiceControl
{
public const string ServiceName = "PortalWorker";
public const string ServiceDisplayName = "Portal Worker";
public const string ServiceDescription = "Process the background jobs for the Portal.";
private AbpBootstrapper _bootstrapper;
public bool Start(HostControl hostControl)
{
_bootstrapper = AbpBootstrapper.Create<PortalServiceModule>();
_bootstrapper.Initialize();
return true;
}
public bool Stop(HostControl hostControl)
{
_bootstrapper.Dispose();
return true;
}
}
现在我可以从Windows服务运行后台作业,虽然我会尝试减少依赖项和重复代码。