-
Notifications
You must be signed in to change notification settings - Fork 4.7k
/
WindowsServiceLifetimeHostBuilderExtensions.cs
147 lines (132 loc) · 6.46 KB
/
WindowsServiceLifetimeHostBuilderExtensions.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting.WindowsServices;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.EventLog;
using Microsoft.Extensions.Options;
namespace Microsoft.Extensions.Hosting
{
/// <summary>
/// Extension methods for setting up WindowsServiceLifetime.
/// </summary>
public static class WindowsServiceLifetimeHostBuilderExtensions
{
/// <summary>
/// Sets the host lifetime to <see cref="WindowsServiceLifetime"/> and enables logging to the event log with
/// the application name as the default source name.
/// </summary>
/// <remarks>
/// This is context aware and will only activate if it detects the process is running as a Windows Service.
/// </remarks>
/// <param name="hostBuilder">The <see cref="IHostBuilder"/> to operate on.</param>
/// <returns>The <paramref name="hostBuilder"/> instance for chaining.</returns>
public static IHostBuilder UseWindowsService(this IHostBuilder hostBuilder)
{
return UseWindowsService(hostBuilder, _ => { });
}
/// <summary>
/// Sets the host lifetime to <see cref="WindowsServiceLifetime"/> and enables logging to the event log with the application
/// name as the default source name.
/// </summary>
/// <remarks>
/// This is context aware and will only activate if it detects the process is running
/// as a Windows Service.
/// </remarks>
/// <param name="hostBuilder">The <see cref="IHostBuilder"/> to operate on.</param>
/// <param name="configure">An <see cref="Action{WindowsServiceLifetimeOptions}"/> to configure the provided <see cref="WindowsServiceLifetimeOptions"/>.</param>
/// <returns>The <paramref name="hostBuilder"/> instance for chaining.</returns>
public static IHostBuilder UseWindowsService(this IHostBuilder hostBuilder, Action<WindowsServiceLifetimeOptions> configure)
{
ThrowHelper.ThrowIfNull(hostBuilder);
if (WindowsServiceHelpers.IsWindowsService())
{
hostBuilder.ConfigureServices(services =>
{
AddWindowsServiceLifetime(services, configure);
});
}
return hostBuilder;
}
/// <summary>
/// Configures the lifetime of the <see cref="IHost"/> built from <paramref name="services"/> to
/// <see cref="WindowsServiceLifetime"/> and enables logging to the event log with the application
/// name as the default source name.
/// </summary>
/// <remarks>
/// This is context aware and will only activate if it detects the process is running
/// as a Windows Service.
/// </remarks>
/// <param name="services">
/// The <see cref="IServiceCollection"/> used to build the <see cref="IHost"/>.
/// For example, <see cref="HostApplicationBuilder.Services"/> or the <see cref="IServiceCollection"/> passed to the
/// <see cref="IHostBuilder.ConfigureServices(Action{HostBuilderContext, IServiceCollection})"/> callback.
/// </param>
/// <returns>The <paramref name="services"/> instance for chaining.</returns>
public static IServiceCollection AddWindowsService(this IServiceCollection services)
{
return AddWindowsService(services, _ => { });
}
/// <summary>
/// Configures the lifetime of the <see cref="IHost"/> built from <paramref name="services"/> to
/// <see cref="WindowsServiceLifetime"/> and enables logging to the event log with the application name as the default source name.
/// </summary>
/// <remarks>
/// This is context aware and will only activate if it detects the process is running
/// as a Windows Service.
/// </remarks>
/// <param name="services">
/// The <see cref="IServiceCollection"/> used to build the <see cref="IHost"/>.
/// For example, <see cref="HostApplicationBuilder.Services"/> or the <see cref="IServiceCollection"/> passed to the
/// <see cref="IHostBuilder.ConfigureServices(Action{HostBuilderContext, IServiceCollection})"/> callback.
/// </param>
/// <param name="configure">An <see cref="Action{WindowsServiceLifetimeOptions}"/> to configure the provided <see cref="WindowsServiceLifetimeOptions"/>.</param>
/// <returns>The <paramref name="services"/> instance for chaining.</returns>
public static IServiceCollection AddWindowsService(this IServiceCollection services, Action<WindowsServiceLifetimeOptions> configure)
{
ThrowHelper.ThrowIfNull(services);
if (WindowsServiceHelpers.IsWindowsService())
{
AddWindowsServiceLifetime(services, configure);
}
return services;
}
private static void AddWindowsServiceLifetime(IServiceCollection services, Action<WindowsServiceLifetimeOptions> configure)
{
#if !NETFRAMEWORK
Debug.Assert(RuntimeInformation.IsOSPlatform(OSPlatform.Windows));
#endif
services.AddLogging(logging =>
{
#if !NETFRAMEWORK
Debug.Assert(RuntimeInformation.IsOSPlatform(OSPlatform.Windows));
#endif
logging.AddEventLog();
});
services.AddSingleton<IHostLifetime, WindowsServiceLifetime>();
services.AddSingleton<IConfigureOptions<EventLogSettings>, EventLogSettingsSetup>();
services.Configure(configure);
}
private sealed class EventLogSettingsSetup : IConfigureOptions<EventLogSettings>
{
private readonly string? _applicationName;
public EventLogSettingsSetup(IHostEnvironment environment)
{
_applicationName = environment.ApplicationName;
}
public void Configure(EventLogSettings settings)
{
#if !NETFRAMEWORK
Debug.Assert(RuntimeInformation.IsOSPlatform(OSPlatform.Windows));
#endif
if (string.IsNullOrEmpty(settings.SourceName))
{
settings.SourceName = _applicationName;
}
}
}
}
}