ABP Windows Service
This is a simple Windows Service built on the ABP Framework (open source) (.NET5 and ABP 4.4.2). The Windows Service uses a local SQL database.
Project Structure:
- AbpWindowsService: This is the Windows Service. You will install this service as Windows Service.
- AbpWindowsService.DbMigrator: You can create your database and update it with DbMigrator.
- AbpWindowsService.Domain: Your domain objects like your entities are in this project.
- AbpWindowsService.Domain.Shared: Shared objects like your entity consts, enums are in this project.
- AbpWindowsService.EntityFrameworkCore: The EFCore referenced project has DbContext and Migrations.
For more information see https://docs.abp.io/en/commercial/latest/startup-templates/application/solution-structure
How to install and run?
Clone this repository to your disk.
Build the solution.
Run the DbMigrator
project to create the database.
Start a command prompt as an administrator and run install-service.bat. This will install the Window Service. Your service name will be AbpWindowsService
. You can change the service name from this code line.
The database connection string is
Server=(LocalDb)\\MSSQLLocalDB;Database=MyDatabase;Trusted_Connection=True
The Trusted_Connection
allows connecting the database with your active Windows user account. But the default user account for Windows Services is a local System
user. Therefore you need to set your active account to the service. To do this; Open the Services window by running C:\Windows\System32\services.msc
and right-click your service, go to "Properties". Go to the "LogOn" tab, choose "This Account" and write your username & password. To learn your logon username, start a command prompt and write whoami
.
Start the service. And that's it!
To check if it's working, open the following logfile
src\AbpWindowsService\bin\Debug\net5.0\win-x64\Logs\Log.txt
I already added 4 database records (books) with the data seeder, so you'll see the following lines in the logs when the service starts. These are the records fetched from the Books
table.
[INF] *** Book name: George Orwell 1984
[INF] *** Book name: Lord of the Flies
[INF] *** Book name: Harry Potter
[INF] *** Book name: The Great Gatsby
How to uninstall?
Start a command prompt as an administrator and run uninstall-service.bat. This will uninstall the Window Service. This batch runs the following operations:
- Stops the service if it's running
- Closes
mmc.exe
if it's open. (because the service cannot be uninstalled if this window is open) - Removes service with
sc delete
command
Creating your own Windows Service in .NET CORE using ABP Framework
Create an ABP console application
To create your own Windows Service, you can start with creating an ABP console application with the following command:
abp new AbpWindowsService -t console -csf
Add Windows Service middleware
Add the Microsoft.Extensions.Hosting.WindowsServices package to your console application by adding the following line to the csproj:
<PackageReference Include="Microsoft.Extensions.Hosting.WindowsServices" Version="5.0.1" />
Open the Program.cs and add the UseWindowsService()
to CreateHostBuilder
method. You can also set a service name to be shown in the services window.
Host.CreateDefaultBuilder(args)
.UseAutofac()
.UseSerilog()
.UseWindowsService(x => x.ServiceName = "AbpWindowsService") //// add this line /////
.ConfigureAppConfiguration((context, config) =>
{
//setup your additional configuration sources
})
.ConfigureServices((hostContext, services) =>
{
services.AddApplication<AbpWindowsServiceModule>();
});
UseWindowsService
makes 3 things:
- Sets the host lifetime to WindowsServiceLifetime
- Sets the Content Root
- Enables logging to the event log with the application name as the default source name
Set log file path
By default, Windows Service runs as a local System account and Serilog will write the logs under C:\Windows\System32
. To overcome this, you can set the log file as the static path. The below code lets Serilog write to the Logs folder under your Windows Service installation directory.
Log.Logger = new LoggerConfiguration()
.MinimumLevel.Debug()
.MinimumLevel.Override("Microsoft", LogEventLevel.Information)
.Enrich.FromLogContext()
.WriteTo.Async(c => c.File(Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "Logs/Log.txt")))
.CreateLogger();
Write your business logic
In your Windows Service, there is an ABP module class AbpWindowsServiceModule.cs
. This class adds the hosted service *HostedService.cs
. Hosted service is an implementation of IHostedService
. It has StartAsync()
and StopAsync()
methods. StartAsync
the method will run when you start your Windows Service and StopAsync
will run when you stop your Windows Service. The application will not end unless you stop it. You can create a domain service from IDomainService
. And write your code in this domain service. Call your method inside the Hosted Service StartAsync
method. Dependency Injection will work without any problem as long as you implement your classes from ITransientDependency
or ISingletonDependency
.
Accessing the database
To access your database and repositories you can move your Windows Service into your main ABP Web Application solution. To do this, copy the service project to the src folder of your main web solution. Add project reference of *.EntityFrameworkCore project to your Windows Service as shown below:
<ProjectReference Include="..\AbpWindowsService.EntityFrameworkCore\AbpWindowsService.EntityFrameworkCore.csproj" />
Add the DependsOn
attribute of EntityFramework
module to your Windows Service as shown below:
[DependsOn(
typeof(AbpAutofacModule),
typeof(AbpWindowsServiceEntityFrameworkCoreModule)) /// added this line ///
]
public class AbpWindowsServiceModule : AbpModule
{
//....
}
Now you can inject your repositories into your domain service.
Don't forget to add the database connection string to the appsettings.json of your Windows Service.
{
"ConnectionStrings": {
"Default": "Server=(LocalDb)\\MSSQLLocalDB;Database=MyDatabase;Trusted_Connection=True"
}
}
Note that we are using Trusted_Connection=True
which means, Windows Authentication (the active Windows user) will be used.
Trusted_Connection=True
will cause a small problem! The default user of a Windows Service is local System account. Therefore you cannot connect your database with the System account. To solve this, apply the 5th step of How to install and run? section in this document. Alternative way; You can create a user in your database and use the UserId-Password credential in the connection string.
And you are ready to install your new service! See the How to install and run? section to install your new service.
Click here to download the sample project
And happy coding!
Comments
Halil İbrahim Kalkan 163 weeks ago
Great article!
TangJun TangJun 163 weeks ago
Great.
amandalawrancee@gmail.com 97 weeks ago
Enable this option to let selected users enroll in offline access on a Windows workstation with a single-factor or multi-factor key. You can set the number of Duo https://www.protectimus.com/guides/winlogon-rdp/ users permitted to use offline access.