Tạo một dịch vụ cho Windows trong .NET 8
Môi trường hoạt động
- Visual Studio
-
- Visual Studio 2022
- .MẠNG
-
- .NET 8
- Windows
-
- cửa sổ 11
Điều kiện tiên quyết
- Visual Studio
-
- Visual Studio 2022
- .MẠNG
-
- .NET 8
- Windows
-
- cửa sổ 10
- cửa sổ 11
- Máy chủ Windows
-
- Windows 2012 trở lên
Điều kiện tiên quyết
- Visual Studio đã được cài đặt
Lúc đầu
Khi tôi cố gắng tạo một dịch vụ Windows trong Visual Studio .NET, chỉ có các mẫu .NET Framework. Nó cũng có thể được tạo trong .NET (Core) và mẫu được đặt tên là "Worker Service".
Trong bài viết này, tôi sẽ giải thích cách sử dụng điều này để tạo, đăng ký và chạy dịch vụ Windows. Nội dung xử lý là tối thiểu, vì vậy nếu bạn có thể xác nhận rằng nó đang chạy dưới dạng dịch vụ Windows, vui lòng tạo hàm.
Tạo dự án
Khởi động Visual Studio. Chọn Tạo dự án mới.
Nhập vào サービス
trường tìm kiếm ở trên, sau đó chọn Dịch vụ Nhân viên từ danh sách.
"Dịch vụ Windows" là phiên bản .NET Framework, không có phiên bản .NET.
Tên dự án và vị trí có thể tùy ý. Nó không ảnh hưởng đến dịch vụ bạn đang đăng ký.
「. NET 8.0 được chọn và để mặc định để tạo nó.
Dự án đã được tạo ra.
Thêm thư viện
Ở trạng thái ban đầu, nó chỉ có chức năng "dịch vụ" và không có chức năng dành riêng cho Windows. Thêm thư viện có thể được sử dụng bởi dịch vụ Windows từ NuGet.
Nhấp chuột phải vào Dependencies và chọn Manage NuGet Packages.
Chọn tab Duyệt qua và nhập vào Microsoft.Extensions.Hosting.WindowsServices
trường tìm kiếm.
Nó sẽ xuất hiện trong danh sách, vì vậy hãy cài đặt nó.
Nhấp vào Áp dụng.
Nó đã được thêm vào như một gói.
Chỉnh sửa chương trình
Lần này, tôi sẽ tạo một dịch vụ định kỳ thêm văn bản vào tệp văn bản với tư cách là Ông / Bà.
Program.cs
Thêm chức năng của dịch vụ Windows như sau:
var builder = Host.CreateApplicationBuilder(args);
// ↓ここから追加
builder.Services.AddWindowsService();
// ↑ここまで追加
builder.Services.AddHostedService<Worker>();
var host = builder.Build();
host.Run();
Worker.cs
Bạn có thể thay đổi tên lớp một cách tùy ý, nhưng trong thời gian này, chúng tôi sẽ để mặc định.
Theo mặc định, chỉ có các phương thức được ExecuteAsync
xử lý khi dịch vụ được thực thi, nhưng hãy thay đổi nó như sau:
public class Worker : BackgroundService
{
private readonly ILogger<Worker> _logger;
<summary>ログの出力先フォルダパス。</summary>
private const string OutputLogFolderPath = @"C:\Temporary\";
/// <summary>ログの出力先ファイルパス。</summary>
private const string OutputLogFilePath = @$"{OutputLogFolderPath}Test.log";
public Worker(ILogger<Worker> logger)
{
_logger = logger;
}
/// <summary>
/// サービスが開始されたときに呼ばれます。
/// </summary>
/// <param name="stoppingToken"></param>
/// <returns></returns>
public override async Task StartAsync(CancellationToken stoppingToken)
{
if (Directory.Exists(OutputLogFolderPath) == false)
{
Directory.CreateDirectory(OutputLogFolderPath);
}
File.AppendAllText(OutputLogFilePath, $"StartAsync サービスを開始しました。\r\n");
await base.StartAsync(stoppingToken);
}
/// <summary>
/// サービスが終了したときに呼ばれます。
/// </summary>
/// <param name="stoppingToken"></param>
/// <returns></returns>
public override async Task StopAsync(CancellationToken stoppingToken)
{
File.AppendAllText(OutputLogFilePath, $"StopAsync サービスを終了しました。\r\n");
File.AppendAllText(OutputLogFilePath, $"------------------------------\r\n");
await base.StopAsync(stoppingToken);
}
/// <summary>
/// サービスが実行されたときに呼ばれます。
/// </summary>
/// <param name="stoppingToken">サービスの非同期キャンセルトークン。</param>
/// <returns></returns>
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
while (!stoppingToken.IsCancellationRequested)
{
File.AppendAllText(OutputLogFilePath, $"{DateTime.Now}\r\n");
if (_logger.IsEnabled(LogLevel.Information))
{
_logger.LogInformation("Worker running at: {time}", DateTimeOffset.Now);
}
await Task.Delay(1000 * 60, stoppingToken);
}
}
}
Chúng tôi đã thêm một phương thức mới và StopAsync
một phương thức mớiStartAsync
.
Như tên của nó, các phương thức này được gọi khi dịch vụ được khởi động và khi nó bị dừng.
Nội dung của quá trình chỉ đơn giản là tạo thư mục và viết văn bản, vì vậy tôi sẽ bỏ qua lời giải thích.
ExecuteAsync
Phương thức tiếp tục lặp lại với stoppingToken cho đến khi while
nó được gắn cờ để hủy.
Thêm những gì while
bạn muốn được xử lý trong khi dịch vụ đang chạy.
Tuy nhiên, nếu bạn chỉ viết quá trình bạn muốn di chuyển, dịch vụ sẽ chạy hết công suất, vì vậy Task.Delay
điều cơ bản là phải di chuyển nó trong khi chờ đợi một thời gian nhất định với phương thức.
Theo mặc định, nó được đặt thành 1 giây (1000ms), vì vậy vui lòng viết lại bất cứ lúc nào.
Gỡ lỗi
Bạn có thể gỡ lỗi từ Visual Studio. Hãy yên tâm rằng bạn sẽ không thực sự được đăng ký với dịch vụ.
Khi bạn chạy nó, bảng điều khiển sẽ xuất hiện.
Nếu quá trình là chính xác, bạn có thể thấy rằng các tập tin đã được tạo.
Nếu bạn muốn dừng gỡ lỗi, hãy đóng bảng điều khiển.
Nếu bạn kiểm tra nhật ký, bạn có thể thấy rằng quá trình khởi động dịch vụ đã qua, nhưng quá trình chấm dứt thì không. Để xem việc chấm dứt, bạn cần thực sự đăng ký với dịch vụ Windows để xác minh nó.
phát
Để có thể đăng ký với dịch vụ Windows, bạn phải xuất bản chương trình. Bấm chuột phải vào dự án và chọn Phát hành.
Chọn Thư mục.
Vị trí thư mục là tốt đẹp theo mặc định.
Cài đặt xuất bản sẽ được tạo, vì vậy hãy chọn "Hiển thị tất cả cài đặt".
Thiết lập nó như sau:
Tên tham số: Nhận xét giá trị | ||
---|---|---|
cấu hình | Phát hành (mặc định) | |
Khung mục tiêu | net8.0 (mặc định) | |
Chế độ triển khai | Phụ thuộc khung | Riêng cho môi trường đăng ký dịch vụ. Nếu bạn đang cài đặt thời gian chạy NEt 8, cài đặt này là OK. |
Thời gian chạy mục tiêu | Chiến thắng-x64 | Nếu HĐH là môi trường 32 bit, hãy chọn win-x86 |
Vị trí mục tiêu | Mặc định | |
Tạo một tệp duy nhất | TRÊN | |
Biên dịch ReadyToRun | tùy tiện |
Sau khi cài đặt, nhấp vào nút "Gửi".
Nếu "Xuất bản thành công" được hiển thị ở góc dưới bên trái, nó đã hoàn tất.
Tệp đầu ra có thể được mở bằng cách nhấp vào "Vị trí mục tiêu".
Vị trí chương trình và ghi danh vào các dịch vụ
Đăng nhập vào môi trường mà bạn muốn đăng ký dịch vụ Windows với đặc quyền quản trị viên.
Sao chép tệp đã phát hành vào môi trường mà bạn muốn đăng ký làm dịch vụ Windows. Bạn có thể đặt nó trong bất kỳ thư mục nào, nhưng hãy nhớ rằng dịch vụ Windows sẽ luôn tham chiếu đến chương trình trong thư mục đó.
Ngoài ra, nếu tệp được xuất bản chứa tệp có phần mở rộng .pdb
, không sao chép nó trong môi trường mà một người không xác định có thể nhìn thấy nó vì nó chứa thông tin phát triển.
Khi tệp đã sẵn sàng, hãy đăng ký nó dưới dạng dịch vụ Windows. Sử dụng lệnh để đăng ký. Nhấp chuột phải vào menu Bắt đầu và chọn "Thiết bị đầu cuối (Quản trị viên)". Ông / Bà đang chạy trong môi trường Windows 11, nhưng trong các môi trường khác, bạn có thể mở dấu nhắc lệnh với đặc quyền quản trị viên.
Trong trường hợp thiết bị đầu cuối, PowerShell có thể được mở trước, nhưng PowerShell có thể không thiết lập được chính xác, vì vậy hãy mở "Dấu nhắc lệnh".
Bạn có thể đăng ký nó với dịch vụ Windows bằng lệnh sau:
định dạng
sc create "<サービス名>" start=auto binpath="<プログラム(.exe)のパス>"
Ví dụ đầu vào
sc create "WindowsServiceDotNet8" start=auto binpath="C:\Service\WindowsServiceDotNet8\WindowsServiceDotNet8.exe"
<サービス名>
là tên xuất hiện trong danh sách các dịch vụ Windows. Bạn có thể đặt tên hiển thị riêng, nhưng nếu bạn không chỉ định tên hiển thị, tên này sẽ được hiển thị.
Nó cũng ảnh hưởng đến sổ đăng ký, vì vậy tên dịch vụ chữ và số được ưu tiên.
start=auto
là cài đặt để tự động khởi động dịch vụ khi Windows khởi động.
Nếu bạn muốn khởi động thủ công, hãy xóa mô tả này.
binpath
là đường dẫn đầy đủ của các tệp chương trình.
Nếu bạn thực hiện lệnh và [SC] CreateService SUCCESS
hiển thị, nó đã thành công.
Các dịch vụ bạn đã đăng ký sẽ xuất hiện trong danh sách.
Khởi động dịch vụ và kiểm tra hoạt động của nó
Nếu bạn muốn chạy dịch vụ, bạn có thể khởi động nó từ màn hình dịch vụ hoặc bằng lệnh sau.
sc start <サービス名>
Lệnh dừng như sau.
sc stop <サービス名>
Nếu bạn dừng dịch vụ, bạn có thể xác minh rằng quá trình tắt máy đang chạy.
Thêm mô tả vào dịch vụ
Trường mô tả của dịch vụ được thêm vào trống, nhưng bạn có thể thêm nó bằng lệnh sau.
sc description <サービス名> "<説明文>"
Xóa dịch vụ
Nếu bạn muốn xóa dịch vụ, bạn có thể làm như vậy bằng lệnh sau. Bạn phải có đặc quyền quản trị viên tại dấu nhắc lệnh.
sc delete <サービス名>