diff --git a/FileSyncAppWin/Program.cs b/FileSyncAppWin/Program.cs
index 0768b4e..82ac696 100644
--- a/FileSyncAppWin/Program.cs
+++ b/FileSyncAppWin/Program.cs
@@ -1,17 +1,164 @@
+using Microsoft.Extensions.Logging;
+using System.IO.Pipes;
+
namespace FileSyncAppWin
{
internal static class Program
{
+
+ private static Mutex mutex = new Mutex(true, "PraewemaFileSyncAppWin");
+ private static volatile bool autoRestart = true;
+ private static ILogger logger;
+ private static Form mainForm;
+ private const string PipeName = "PraewemaFileSyncAppWinPipe";
+
///
/// The main entry point for the application.
///
[STAThread]
- static void Main()
+ static void Main(string[] args)
{
- // To customize application configuration such as set high DPI settings or default font,
- // see https://aka.ms/applicationconfiguration.
- ApplicationConfiguration.Initialize();
- Application.Run(new MainForm());
+ FileSyncApp.Program.ConfigureLogger();
+ logger = FileSyncApp.Program.LoggerFactory.CreateLogger("FileSyncAppWin");
+ if (args.Contains("noautorestart"))
+ {
+ logger?.LogInformation("startup argument noautorestart given, settings autoRestart to false");
+ autoRestart = false;
+ }
+ if (args.Contains("restart"))
+ {
+ logger?.LogInformation("startup argument restart given, sending exit signal to running instance");
+ SendExitSignalToFirstInstance();
+ }
+ logger?.LogInformation("try to get mutex");
+ // Try to acquire the mutex
+ if (!mutex.WaitOne(TimeSpan.FromSeconds(15)))
+ {
+ // Mutex was not acquired, meaning another instance is running
+
+ Console.WriteLine("FileSyncAppWin another instance is running, exiting.");
+ logger?.LogInformation("FileSyncAppWin another instance is running, exiting.");
+ return; // Exit the second instance
+ }
+
+ try
+ {
+ var pipeServer = new NamedPipeServerStream(PipeName, PipeDirection.InOut);
+ // Start listening for incoming connections
+ pipeServer.BeginWaitForConnection(PipeConnectedCallback, pipeServer);
+
+ logger?.LogInformation("FileSyncAppWin Main program starting...");
+ Application.ThreadException += Application_ThreadException;
+ Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException);
+ AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException;
+ ApplicationConfiguration.Initialize();
+ mainForm = new MainForm();
+ Application.Run(mainForm);
+ }
+ catch (Exception exception)
+ {
+ logger?.LogError(exception, "FileSyncAppWin exception in main logic");
+ }
+ finally
+ {
+ logger?.LogInformation("FileSyncAppWin releasing mutex");
+ mutex.ReleaseMutex();
+ }
+
+ }
+
+ private static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
+ {
+ try
+ {
+ logger?.LogCritical((Exception)e.ExceptionObject, "CurrentDomain_UnhandledException isTerminating {A}", e.IsTerminating);
+ }
+ catch (Exception castException)
+ {
+ logger?.LogCritical(castException, "CurrentDomain_UnhandledException, Exception object {@A}", e.ExceptionObject);
+ }
+ //if (e.IsTerminating)
+ {
+ RestartApplication();
+ }
+
+ }
+
+ private static void Application_ThreadException(object sender, ThreadExceptionEventArgs e)
+ {
+ logger?.LogCritical(e.Exception, "Application_ThreadException");
+ RestartApplication();
+ }
+
+ private static void PipeConnectedCallback(IAsyncResult result)
+ {
+ var pipeServer = (NamedPipeServerStream)result.AsyncState;
+
+ try
+ {
+ // End waiting for the connection
+ pipeServer.EndWaitForConnection(result);
+
+ // Read the message from the pipe
+ using (var reader = new StreamReader(pipeServer))
+ {
+ string message = reader.ReadLine();
+ if (message == "Exit")
+ {
+ logger?.LogInformation("Received exit signal from second instance. Exiting gracefully.");
+ mainForm.Close();
+ //Environment.Exit(0); // Gracefully exit the application
+ }
+ }
+
+ // Close the pipe
+ pipeServer.Close();
+ }
+ catch (Exception ex)
+ {
+ logger?.LogError(ex, "Error handling named pipe connection.");
+ }
+ }
+
+ private static void SendExitSignalToFirstInstance()
+ {
+ try
+ {
+ using (var pipeClient = new NamedPipeClientStream(".", PipeName, PipeDirection.Out))
+ {
+ pipeClient.Connect(500); // Connect with a timeout
+
+ // Send an exit signal
+ using (var writer = new StreamWriter(pipeClient))
+ {
+ writer.WriteLine("Exit");
+ }
+ }
+ }
+ catch (Exception ex)
+ {
+ logger?.LogError(ex, "Error sending exit signal to first instance.");
+ }
+ }
+
+
+ private static void RestartApplication()
+ {
+ if (autoRestart)
+ {
+ // Get the path of the current application
+ string assemblyPath = System.Diagnostics.Process.GetCurrentProcess().MainModule.FileName;
+ // Restart the application using the path
+ logger?.LogInformation("RestartApplication, starting new process {A}", assemblyPath);
+ System.Diagnostics.Process.Start(assemblyPath);
+
+ // Exit the current instance of the application
+ Environment.Exit(0);
+ }
+ else
+ {
+ logger?.LogInformation("RestartApplication, skip starting new process -> autoRestart=false");
+ }
}
}
}
\ No newline at end of file
diff --git a/FileSyncLibNet/FileCleanJob/FileCleanJob.cs b/FileSyncLibNet/FileCleanJob/FileCleanJob.cs
index 48f4053..2950f38 100644
--- a/FileSyncLibNet/FileCleanJob/FileCleanJob.cs
+++ b/FileSyncLibNet/FileCleanJob/FileCleanJob.cs
@@ -31,7 +31,7 @@ public static IFileJob CreateJob(IFileCleanJobOptions fileCleanJobOptions)
// try
// {
// Dictionary pathMaxDays = new Dictionary();
- // string[] subFolders = { "HriFFTLog", "HriShockLog", "HriLog", "HriDebugLog", "raw" };
+ //
// var driveInfo = new DriveInfo(Hauptprogramms.First().ProductionDataPath);
// int days = 59;
diff --git a/FileSyncLibNet/FileSyncJob/FileSyncJobOptionsBuilder.cs b/FileSyncLibNet/FileSyncJob/FileSyncJobOptionsBuilder.cs
index 7a1badc..61517e8 100644
--- a/FileSyncLibNet/FileSyncJob/FileSyncJobOptionsBuilder.cs
+++ b/FileSyncLibNet/FileSyncJob/FileSyncJobOptionsBuilder.cs
@@ -81,6 +81,11 @@ public IFileSyncJobOptionsBuilderSetProperties WithSubfolder(string subfolder)
jobOptions.Subfolders.Add(subfolder);
return this;
}
+ public IFileSyncJobOptionsBuilderSetProperties WithSubfolders(params string[] subfolders)
+ {
+ jobOptions.Subfolders.AddRange(subfolders);
+ return this;
+ }
public IFileSyncJobOptionsBuilderSetProperties DeleteAfterBackup(bool deleteAfterBackup)
{
jobOptions.DeleteSourceAfterBackup = deleteAfterBackup;
@@ -136,6 +141,7 @@ public interface IFileSyncJobOptionsBuilderSetProperties : IFileSyncJobOptionsBu
IFileSyncJobOptionsBuilderSetProperties WithCredentials(NetworkCredential networkCredential);
IFileSyncJobOptionsBuilderSetProperties WithSearchPattern(string searchPattern);
IFileSyncJobOptionsBuilderSetProperties WithSubfolder(string subfolder);
+ IFileSyncJobOptionsBuilderSetProperties WithSubfolders(params string[] subfolders);
IFileSyncJobOptionsBuilderSetProperties DeleteAfterBackup(bool deleteAfterBackup);
IFileSyncJobOptionsBuilderSetProperties WithLogger(ILogger logger);
IFileSyncJobOptionsBuilderSetProperties WithLogger(Action loggerAction);
diff --git a/FileSyncLibNet/SyncProviders/FileIOProvider.cs b/FileSyncLibNet/SyncProviders/FileIOProvider.cs
index c53bbd5..68a14d5 100644
--- a/FileSyncLibNet/SyncProviders/FileIOProvider.cs
+++ b/FileSyncLibNet/SyncProviders/FileIOProvider.cs
@@ -240,7 +240,7 @@ void EnsureAccess()
// catch { log.LogInformation($"Konnte nicht auf Backuppfad {backupTarget} schreiben"); canWrite = false; }
// }
// if (canWrite)
- // foreach (string folder in new string[] { "HriFFTLog", "HriShockLog", "HriLog", "HriDebugLog", "HRI" })
+ //
// {
// string _path = Path.Combine(ProductionDataPath, folder);
// if (!Directory.Exists(_path))