hikvision-sync-service/Program.cs

123 lines
4.1 KiB
C#

using System;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.ServiceProcess;
using System.Threading;
using System.Threading.Tasks;
namespace HikvisionAttendanceService;
internal static class Program
{
[DllImport("kernel32.dll", SetLastError = true)]
private static extern bool AllocConsole();
private static bool ArgsContainFlag(string[] args, string flag) =>
args.Any(a => string.Equals(a, flag, StringComparison.OrdinalIgnoreCase));
private static bool ArgsContainTestFlag(string[] args) =>
ArgsContainFlag(args, "--test");
private static bool ShouldRunAsConsole(string[] args)
{
if (ArgsContainFlag(args, "--console") || ArgsContainFlag(args, "--debug"))
return true;
// F5 / Debug from Visual Studio / Cursor: run interactively instead of ServiceBase.
if (Debugger.IsAttached)
return true;
// Double-click / direct run of exe outside SCM.
if (Environment.UserInteractive)
return true;
return false;
}
private static async Task Main(string[] args)
{
if (ArgsContainTestFlag(args))
{
Console.WriteLine("Program entry (test): rawArgCount=" + args.Length + " rawArgs=" + string.Join(" ", args));
await AttendanceTestMode.RunAsync(args).ConfigureAwait(false);
return;
}
if (ShouldRunAsConsole(args))
{
await RunConsoleHostAsync(args).ConfigureAwait(false);
return;
}
ServiceBase.Run(new ServiceBase[]
{
new HikvisionAttendanceWindowsService()
});
}
/// <summary>
/// Same runtime path as the Windows Service OnStart/OnStop, but runnable under debugger (F5).
/// Press Ctrl+C (or Stop Debugging) to shut down cleanly.
/// </summary>
private static async Task RunConsoleHostAsync(string[] args)
{
try
{
// Make console output visible when debugging a WinExe project.
if (Environment.UserInteractive)
AllocConsole();
}
catch
{
// ignore: console may already exist
}
Environment.CurrentDirectory = AppContext.BaseDirectory;
var baseDir = AppContext.BaseDirectory;
var configPath = Path.Combine(baseDir, "serviceconfig.json");
if (!File.Exists(configPath))
configPath = Path.Combine(baseDir, "appsettings.json");
var config = HikvisionAttendanceWindowsService.HikvisionServiceConfig.Load(configPath);
var logger = new HikvisionAttendanceWindowsService.FileLogger(config.LogDirectory);
Console.WriteLine("HikvisionAttendanceService console/debug host starting...");
Console.WriteLine("Config: " + configPath);
Console.WriteLine("LogDirectory: " + config.LogDirectory);
Console.WriteLine("Press Ctrl+C to stop.");
logger.Ops(OpsMarkers.Service, "CONSOLE HOST START time=" + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") +
" config=\"" + configPath + "\" debuggerAttached=" + Debugger.IsAttached);
using var cts = new CancellationTokenSource();
Console.CancelKeyPress += (_, e) =>
{
e.Cancel = true;
Console.WriteLine("Shutdown requested...");
logger.Ops(OpsMarkers.Service, "STOP REQUESTED reason=\"Ctrl+C\"");
cts.Cancel();
};
using var manager = new HikvisionAttendanceManager(config, logger);
try
{
await manager.RunAsync(cts.Token).ConfigureAwait(false);
}
catch (OperationCanceledException)
{
// expected on stop
}
catch (Exception ex)
{
logger.Error("Console/debug host failed", ex);
logger.OpsError(OpsMarkers.Service, "CONSOLE HOST FAILED reason=\"" + ex.Message + "\"");
Console.WriteLine("FATAL: " + ex.Message);
throw;
}
logger.Ops(OpsMarkers.Service, "CONSOLE HOST END");
Console.WriteLine("HikvisionAttendanceService stopped.");
}
}