使用.NET Core 3.1構建Windows Worker服務以刪除文件夾中的舊文件

目錄

免責聲明

介紹

解決方案

添加配置設置

添加帶有文件夾列表的配置文件

我們的代碼

將應用程序轉換爲Windows服務


創建Windows服務曾經是一個繁瑣的過程,但是隨着.NET Core 3.0中引入的新工作程序服務框架變得更加容易。本文中的代碼主要是爲了向讀者介紹輔助服務,並說明如何將輔助服務部署爲Windows服務,但希望該應用程序本身也具有實際用途。

免責聲明

我們在此處創建的服務用於從獨立配置文件中指定的文件夾列表中刪除早於特定日期的文件。該應用程序已經過測試,據我所知它可以在我的環境中運行。我不保證它將在您的環境中完美無缺。在生產環境中使用此功能之前,強烈建議您執行一些其他測試。

介紹

在本文中,我將介紹如何在Visual Studio中使用Worker Service模板創建簡單的Windows Service

在引入.NET Core 3.0中的Worker Services之前,您可能會使用.NET Windows Service模板創建Windows服務。我一直認爲,使用該模板的經驗從來都不是很直觀的。您可能會遇到的第一個問題是,如果不實現某些代碼黑客,就無法在Visual Studio環境中運行該服務。此外,該模板並沒有爲您提供使服務按預期運行所需的實際指導。幸運的是,有了.NET 3.0Worker Services,所有這些都變得更加容易。

解決方案

要閱讀本文,您需要在您的環境中安裝Visual Studio 2019.NET Core 3.0

首先,您需要創建一個新項目,並選擇下圖所示的工作流程模板:

添加配置設置

appsettings.json文件中,我們將需要添加一些配置。一個配置的閾值,說明最大允許年齡的文件之前,我們刪除它。讓我們將此設置稱爲NumberOfDaysBeforeDelete。我將此值設置爲90天。除此之外,我們需要包含要監視的文件夾列表的獨立配置文件的文件路徑。我將其稱爲ConfigurationFilePath設置,並將其指向我的c:\temp文件夾中的某個位置。需要最後一個設置來配置此服務將執行我們的自定義代碼的時間間隔。我稱這個設置爲RunIntervallInHours,然後將值設置爲12小時,這意味着該服務每天兩次檢查配置文件中每個文件夾的內容,並刪除最後寫入日期超過90天的所有文件。這三個配置設置被分組爲appsettings.json文件中的一個節點,我稱之爲App.Configurations,請參見以下內容:

{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft": "Warning",
      "Microsoft.Hosting.Lifetime": "Information"
    }
  },
  "App.Configurations": {
    "ConfigurationFilePath": "C:\\Temp\\CleanUpFolders\\CleanUpConfigurations.config",
    "NumberOfDaysBeforeDelete": "10",
    "RunIntervallInHours": "12"
  }
}

請注意,您的項目中同時有一個appsetttings.json文件和一個appsettings.development.json文件。在運行時使用哪個appsettings.json文件取決於您的環境設置。從Visual Studio運行此服務時,默認情況下將使用文件Properties/launchSettings.json配置的開發設置。

添加帶有文件夾列表的配置文件

我在c:\Temp\CleauUpFoders\創建一個名爲CleanUpConfigurations.config的文件,並將以下兩行放入其中:

C:\Temp\CleanUpFolders\Folder1
C:\Temp\CleanUpFolders\Folder2

我還在同一位置創建文件夾Folder1Folder2

我們的代碼

在新創建的解決方案中,最初需要我們關注兩個文件,用於啓動應用程序的program.cs和包含該解決方案的自定義代碼的worker.cs。在program.cs文件中,您將找到用於設置主機環境的代碼。爲了便於將此應用程序作爲Windows服務運行,您需要添加以下NuGet軟件包。

Install-Package Microsoft.Extensions.Hosting.WindowsServices

安裝該軟件包後,您可以在Host.CreateDefaultBuilder(args)後面添加行.UseWindowsService(),以便最終在program.cs文件中添加以下內容。

public class Program
    {
        public static void Main(string[] args)
        {
            CreateHostBuilder(args).Build().Run();
        }

        public static IHostBuilder CreateHostBuilder(string[] args) =>
            Host.CreateDefaultBuilder(args)
            .UseWindowsService()
                .ConfigureServices((hostContext, services) =>
                {
                    services.AddHostedService<worker>();
                });
    }

worker.cs文件中,我們首先將IServiceScopeFactory實例插入構造函數。這將用於訪問appsettings配置文件。

public Worker(ILogger<worker> logger, IServiceScopeFactory serviceScopeFactory)
        {
            _logger = logger;
            _serviceScopeFactory = serviceScopeFactory;
        }

爲了確保每次啓動服務時都讀取配置,我重寫了該方法StartAsync並在此處檢索我的應用程序配置:

public override Task StartAsync(CancellationToken cancellationToken)
        {
            _configuration = _serviceScopeFactory.CreateScope().
                             ServiceProvider.GetRequiredService<iconfiguration>();
            _numberOfDaysBeforeDelete = int.Parse(_configuration
                                        ["App.Configurations:NumberOfDaysBeforeDelete"]);
            _runIntervallInHours = int.Parse(_configuration
                                            ["App.Configurations:RunIntervallInHours"]);
            _folderPaths = File.ReadAllLines(_configuration
            ["App.Configurations:ConfigurationFilePath"]).Select(x => x.Trim()).ToList();

            return base.StartAsync(cancellationToken);
        }

請注意,我是如何從ConfigurationFilePath設置中所述文件中讀取所有行並將其放入list _folderPaths的。

Worker類中聲明以下變量:

private IList<string> _folderPaths;
private int _numberOfDaysBeforeDelete;
private int _runIntervallInHours;

從我們的配置文件中檢索文件夾並刪除所有90天以上的文件的代碼將放置在該ExecuteAsync方法中。ExecuteAsyncCancellationToken作爲參數。CancellationToken非常重要,因爲它將用於識別服務何時停止。發生這種情況時,屬性IsCancellationRequested將設置爲true。因此,我們ExecuteAsync代碼的第一行是:

while (!stoppingToken.IsCancellationRequested)

我將在此方法中進一步檢查IsCancellationRequested,以確保在收到取消請求時儘快停止執行。用於獲取文件天數x天以上並刪除它們的代碼分爲兩行:

var files = Directory.GetFiles(path).Select(file => new FileInfo(file)).Where
(file => file.LastWriteTime < DateTime.Now.AddDays(-1* _numberOfDaysBeforeDelete)).ToList();

// Delete found files
files.ForEach(file => file.Delete());

在關閉while循環之前,我延遲了一下。由於我們的setting _runIntervallInHours時間設置爲12小時,因此該代碼將使服務停止12小時,然後再繼續執行。

await Task.Delay(TimeSpan.FromHours(_runIntervallInHours), stoppingToken);

請注意,此處使用了取消標記,這會導致Windows服務停止時取消等待過程。

ExecuteAsync方法的完整代碼如下所示:

protected override async Task ExecuteAsync(CancellationToken stoppingToken)
        {
            while (!stoppingToken.IsCancellationRequested)
            {
                _logger.LogInformation("Worker running at: {time}", DateTimeOffset.Now);

                foreach (var path in _folderPaths)
                {
                    if (!stoppingToken.IsCancellationRequested)
                    {
                        // Get old files
                        var files = Directory.GetFiles(path).Select
                                    (file => new FileInfo(file)).Where
                                    (file => file.LastWriteTime < DateTime.Now.AddDays
                                             (-1* _numberOfDaysBeforeDelete)).ToList();

                        // Delete found files
                        files.ForEach(file => file.Delete());
                    }
                }
                
                await Task.Delay(TimeSpan.FromHours(_runIntervallInHours), stoppingToken);
            }
        }

那就是我們需要的所有代碼。您只需按F5鍵,然後直接從Visual Studio運行該應用程序,然後看它是否有效。

將應用程序轉換爲Windows服務

現在繼續併發布應用程序。

到文件夾:

以管理員身份打開PowerShell終端並運行以下命令:

sc.exe create FolderCleanUpService binpath= "C:\Apps\FolderCleanUpService.exe" start= auto

這會將服務安裝在Windows計算機上。

您可以將服務放置在所需的任何位置,我在這裏選擇將其放置在CApps文件夾中。我使用該標誌來確保Windows啓動時自動啓動該服務。要設置服務描述,您需要執行第二條命令:start=auto

sc.exe description "FolderCleanUpService" 
"This service monitors and deletes files older than 90 days"

按(Window + R)並運行命令services.msc,然後您應該會看到所有服務的列表,並且在該列表中您應該能夠看到該FolderCleanUpService服務。您需要首次手動啓動它,但是由於啓動類型設置爲自動,因此它將在重新啓動後自動自行啓動。

您可以使用以下命令刪除服務:

sc.exe delete "FolderCleanUpService"

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章