377 lines
12 KiB
C#
377 lines
12 KiB
C#
using IOB_MAN.Core.Services;
|
|
using Microsoft.AspNetCore.Components.WebView.WindowsForms;
|
|
using Microsoft.Extensions.DependencyInjection;
|
|
using NLog;
|
|
using System.Diagnostics;
|
|
using System.Reflection;
|
|
|
|
namespace IOB_MAN
|
|
{
|
|
public partial class BlazorForm : Form
|
|
{
|
|
#region Public Constructors
|
|
|
|
public BlazorForm()
|
|
{
|
|
InitializeComponent();
|
|
ServiceInit();
|
|
ConfInit();
|
|
InitBlazorView();
|
|
StartTimer();
|
|
CheckMemory();
|
|
}
|
|
|
|
#endregion Public Constructors
|
|
|
|
#region Public Methods
|
|
|
|
/// <summary>
|
|
/// Force restart application, with delay
|
|
/// </summary>
|
|
public static void RestartApplication(bool force)
|
|
{
|
|
if (force)
|
|
{
|
|
Log.Info($"Chiamata restart application forzato");
|
|
}
|
|
else
|
|
{
|
|
Log.Info($"Chiamata restart application x superamento soglia GC consecutivi");
|
|
}
|
|
string exePath = Application.ExecutablePath;
|
|
// fermo tutti i sw controllati...
|
|
ACService.DoCloseAll(false);
|
|
Log.Info($"Completata chiusura processi x restart");
|
|
|
|
// Use cmd.exe to delay start until current app exits
|
|
int restartDelay = 5;
|
|
ProcessStartInfo psi = new ProcessStartInfo("cmd.exe", $"/C timeout /t {restartDelay} & start \"\" \"{exePath}\"")
|
|
{
|
|
CreateNoWindow = true,
|
|
UseShellExecute = false
|
|
};
|
|
|
|
Process.Start(psi);
|
|
Log.Info($"Avviato task di riavvio post delay {restartDelay}sec");
|
|
|
|
// Now safely exit the current instance
|
|
Application.Exit();
|
|
}
|
|
|
|
#endregion Public Methods
|
|
|
|
#region Protected Fields
|
|
|
|
/// <summary>
|
|
/// Dataora prossima scadenza riavvio automatico
|
|
/// </summary>
|
|
protected DateTime tOutAutocheck = DateTime.Now;
|
|
|
|
#endregion Protected Fields
|
|
|
|
#region Private Fields
|
|
|
|
/// <summary>
|
|
/// Classe logger
|
|
/// </summary>
|
|
private static Logger Log = LogManager.GetCurrentClassLogger();
|
|
|
|
private int currSeqGC = 0;
|
|
|
|
/// <summary>
|
|
/// Memoria dotNet allocata
|
|
/// </summary>
|
|
private long dotNetMemUsed = 0;
|
|
|
|
private DateTime LastForcedGC = DateTime.Now;
|
|
|
|
private int maxConsGC = 5;
|
|
|
|
/// <summary>
|
|
/// Max memoria consumabile (std 128Mb)
|
|
/// </summary>
|
|
private double maxMemoryLimitMb = 128.0;
|
|
|
|
/// <summary>
|
|
/// Memoria totale processo
|
|
/// </summary>
|
|
private long totalMemUsed = 0;
|
|
|
|
#endregion Private Fields
|
|
|
|
#region Private Properties
|
|
|
|
private static AppControlService ACService { get; set; } = null!;
|
|
|
|
private static FluxLogManService FLMService { get; set; } = null!;
|
|
|
|
private double dotNetMemUsedMb
|
|
{
|
|
get => dotNetMemUsed / 1024.0 / 1024.0;
|
|
}
|
|
|
|
private Size lastSize { get; set; } = new Size(1200, 700);
|
|
|
|
private double totalMemUsedMb
|
|
{
|
|
get => totalMemUsed / 1024.0 / 1024.0;
|
|
}
|
|
|
|
#endregion Private Properties
|
|
|
|
#region Private Methods
|
|
|
|
/// <summary>
|
|
/// Esecuzione del processo di restart
|
|
/// </summary>
|
|
private static void DoRestart(bool fullRestart)
|
|
{
|
|
// full restart usa sw esterno, altrimenti solo app che riparte SENZA check update esterno
|
|
if (fullRestart)
|
|
{
|
|
// uso restarter esterno...
|
|
Assembly assembly = Assembly.GetExecutingAssembly();
|
|
string startDir = Path.GetDirectoryName(assembly.Location)!;
|
|
string extPath = Path.Combine(startDir, "libs", "EgwAccRestarter.exe");
|
|
// uso processstartInfo x nascondere finestra
|
|
ProcessStartInfo startInfo = new ProcessStartInfo();
|
|
startInfo.WindowStyle = ProcessWindowStyle.Normal;
|
|
startInfo.CreateNoWindow = true;
|
|
startInfo.FileName = extPath;
|
|
Process.Start(startInfo);
|
|
}
|
|
else
|
|
{
|
|
Application.Restart();
|
|
Environment.Exit(0);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Riavvio il timer...
|
|
/// </summary>
|
|
/// <exception cref="NotImplementedException"></exception>
|
|
private void ACService_EA_ConfigUpdated()
|
|
{
|
|
timerUI.Stop();
|
|
timerTask.Stop();
|
|
tOutAutocheck = ACService.VetoAutoCheck;
|
|
StartTimer();
|
|
}
|
|
|
|
private void ACService_EA_RebootRequested()
|
|
{
|
|
Log.Info("---------------------------------------");
|
|
Log.Info("Starting Reboot Request");
|
|
Log.Info("---------------------------------------");
|
|
timerUI.Stop();
|
|
timerUI.Dispose();
|
|
timerTask.Stop();
|
|
timerTask.Dispose();
|
|
ACService.DoCloseAll(false);
|
|
RestartApplication(true);
|
|
}
|
|
|
|
private void ACService_EA_ReloadRequested()
|
|
{
|
|
// effettua chiamata reload
|
|
DoRestart(false);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gestione evento restart applicazione
|
|
/// </summary>
|
|
private void ACService_EA_RestartRequested()
|
|
{
|
|
// effettua chiamata restart
|
|
DoRestart(true);
|
|
}
|
|
|
|
private void BlazorForm_FormClosing(object sender, FormClosingEventArgs e)
|
|
{
|
|
ACService.EA_ConfigUpdated -= ACService_EA_ConfigUpdated;
|
|
ACService.EA_RestartRequested -= ACService_EA_RestartRequested;
|
|
ACService.EA_ReloadRequested -= ACService_EA_ReloadRequested;
|
|
ACService.EA_RebootRequested -= ACService_EA_RebootRequested;
|
|
FLMService.EA_FluxLogReq -= FLMService_EA_FluxLogReq;
|
|
timerUI.Stop();
|
|
timerUI.Dispose();
|
|
timerTask.Stop();
|
|
timerTask.Dispose();
|
|
ACService.DoCloseAll(false);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Evento completamento caricamento app
|
|
/// </summary>
|
|
/// <param name="sender"></param>
|
|
/// <param name="e"></param>
|
|
private void BlazorForm_Load(object sender, EventArgs e)
|
|
{
|
|
SetPosition();
|
|
}
|
|
|
|
/// <summary>
|
|
/// effettua controllo memoria + log
|
|
/// se occupa più di maxMemoryLimitMb --> chiama GC
|
|
/// </summary>
|
|
private void CheckMemory()
|
|
{
|
|
dotNetMemUsed = GC.GetTotalMemory(false); // Pass 'true' to force a garbage collection first
|
|
Process currentProcess = Process.GetCurrentProcess();
|
|
totalMemUsed = currentProcess.PrivateMemorySize64;
|
|
|
|
Log.Info($"Memory Usage | {dotNetMemUsedMb:F2} / {totalMemUsedMb:F2} MB | Managed / Total");
|
|
if (dotNetMemUsedMb > maxMemoryLimitMb / 2 || totalMemUsedMb > maxMemoryLimitMb)
|
|
{
|
|
// chiamo GC forzatamente
|
|
currSeqGC++;
|
|
Log.Info($"Chiamato forzatamente GC.Collect per superamento limite memoria | count: {currSeqGC}");
|
|
GC.Collect();
|
|
// registro forced GC
|
|
LastForcedGC = DateTime.Now;
|
|
if (currSeqGC > maxConsGC)
|
|
{
|
|
Log.Info("---------------------------------------");
|
|
Log.Info($"Superato limite GC consecutivi | count: {currSeqGC}");
|
|
RestartApplication(false);
|
|
}
|
|
}
|
|
else if (DateTime.Now.Subtract(LastForcedGC).TotalHours > 1)
|
|
{
|
|
// chiamo GC forzatamente
|
|
Log.Info($"Chiamato forzatamente GC.Collect per scadenza periodo");
|
|
GC.Collect();
|
|
// registro forced GC
|
|
LastForcedGC = DateTime.Now;
|
|
}
|
|
else
|
|
{
|
|
if (currSeqGC > 0)
|
|
{
|
|
currSeqGC--;
|
|
Log.Info($"Riduzione contatore GC consecutivi | count: {currSeqGC}");
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Init conf accessorie
|
|
/// </summary>
|
|
private void ConfInit()
|
|
{
|
|
// recupero limite memoria prima del GC
|
|
maxMemoryLimitMb = ACService.MaxMemGc;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Richiesta apertura nuova form x editing FluxLog: la implemento leggendo il codIOB e lo passo al controllo...
|
|
/// </summary>
|
|
/// <param name="codIOB"></param>
|
|
private void FLMService_EA_FluxLogReq(string codIOB)
|
|
{
|
|
// chiamo nuova form con parametro x CodIOB richiesto
|
|
FluxLogData FldForm = new FluxLogData(FLMService, codIOB);
|
|
FldForm.Show();
|
|
}
|
|
|
|
private void InitBlazorView()
|
|
{
|
|
Stopwatch sw = new Stopwatch();
|
|
sw.Start();
|
|
try
|
|
{
|
|
Log.Trace($"TrayMenu OK | {sw.ElapsedMilliseconds}ms");
|
|
var services = new ServiceCollection();
|
|
Log.Trace($"Add ServiceCollection | {sw.ElapsedMilliseconds}ms");
|
|
services.AddWindowsFormsBlazorWebView();
|
|
Log.Trace($"Add AddWindowsFormsBlazorWebView | {sw.ElapsedMilliseconds}ms");
|
|
services.AddSingleton<AppControlService>(ACService);
|
|
services.AddSingleton<FluxLogManService>(FLMService);
|
|
Log.Trace($"Add Singleton Services | {sw.ElapsedMilliseconds}ms");
|
|
blazorWebView1.HostPage = "wwwroot\\index.html";
|
|
blazorWebView1.Services = services.BuildServiceProvider();
|
|
blazorWebView1.RootComponents.Add<MainBlazor>("#app");
|
|
Log.Trace($"Add MainBlazor | {sw.ElapsedMilliseconds}ms");
|
|
}
|
|
catch (Exception exc)
|
|
{
|
|
Log.Error($"Exception during setartup{Environment.NewLine}{exc}");
|
|
}
|
|
}
|
|
|
|
private void ServiceInit()
|
|
{
|
|
//init preliminare servizio controllo
|
|
ACService = new AppControlService(true);
|
|
FLMService = new FluxLogManService();
|
|
ACService.EA_ConfigUpdated += ACService_EA_ConfigUpdated;
|
|
ACService.EA_RestartRequested += ACService_EA_RestartRequested;
|
|
ACService.EA_ReloadRequested += ACService_EA_ReloadRequested;
|
|
ACService.EA_RebootRequested += ACService_EA_RebootRequested;
|
|
FLMService.EA_FluxLogReq += FLMService_EA_FluxLogReq;
|
|
}
|
|
|
|
private void SetPosition()
|
|
{
|
|
// posiziono in basso a sx...
|
|
Rectangle workArea = Screen.GetWorkingArea(this);
|
|
this.Location = new Point((workArea.Right - lastSize.Width) / 2, (workArea.Bottom - lastSize.Height) / 2);
|
|
}
|
|
|
|
private void StartTimer()
|
|
{
|
|
// timer controlli da conf
|
|
timerUI.Interval = (ACService.RefreshPeriod);
|
|
timerTask.Interval = (ACService.CheckRestartPeriod);
|
|
timerMemCheck.Interval = (ACService.CheckMemoryPeriod);
|
|
// avvio timers
|
|
timerUI.Start();
|
|
Thread.Sleep(50);
|
|
timerTask.Start();
|
|
Thread.Sleep(50);
|
|
timerMemCheck.Start();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Evento timer memory check periodico
|
|
/// </summary>
|
|
/// <param name="sender"></param>
|
|
/// <param name="e"></param>
|
|
private void timerMemCheck_Tick(object sender, EventArgs e)
|
|
{
|
|
CheckMemory();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Timer task x eventuale riavvio processi fermi SE abilitato...
|
|
/// </summary>
|
|
/// <param name="sender"></param>
|
|
/// <param name="e"></param>
|
|
private void timerTask_Tick(object sender, EventArgs e)
|
|
{
|
|
// fermo task...
|
|
timerTask.Stop();
|
|
// esegue controllo task x eventuale autorestart
|
|
ACService.DoAutoRestart(false);
|
|
// riavvio task x evitare sovrapposizioni in debug
|
|
timerTask.Start();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Esecuzione task di verifica stato app
|
|
/// </summary>
|
|
/// <param name="sender"></param>
|
|
/// <param name="e"></param>
|
|
private async void timerUI_Tick(object sender, EventArgs e)
|
|
{
|
|
// fermo task...
|
|
timerUI.Stop();
|
|
await ACService.DoScan();
|
|
// riavvio task x evitare sovrapposizioni in debug
|
|
timerUI.Start();
|
|
}
|
|
|
|
#endregion Private Methods
|
|
}
|
|
} |