using EgwCoreLib.Utils; using IOB_MAN.Core.Config; using IOB_MAN.Core.Data; using IOB_MAN.Core.Models; using Newtonsoft.Json; using NLog; using StackExchange.Redis; using System.Collections.Concurrent; using System.Diagnostics; using static IOB_MAN.Core.CoreEnum; namespace IOB_MAN.Core.Services { public class AppControlService : IAppControlService, IDisposable { #region Public Constructors /// /// Init classe /// /// Se True avvia i processi gestiti public AppControlService(bool startProc) { LoadConfAndStart(startProc); } #endregion Public Constructors #region Public Events /// /// Evento update configurazione /// public event Action EA_ConfigUpdated = null!; /// /// Evento richiesta reboot completo applicazione /// public event Action EA_RebootRequested = null!; /// /// Evento update status controlli /// public event Action EA_StatusUpdated = null!; #endregion Public Events #region Public Properties /// /// Abilitazione autorestart /// public bool AutoRestartEnabled { get; set; } = true; /// /// Periodo controllo memoria in msec /// public int CheckMemoryPeriod { get => currAppConf.TaskData.TimerMemSec * 1000; } public int CheckRestartPeriod { get => currAppConf.TaskData.TimerCheckMSec; set => currAppConf.TaskData.TimerCheckMSec = value; } public string ConfDirIob { get => confDirIob; set => confDirIob = value; } /// /// Configurazione IOB in sola lettura /// public IobManConfig CurrIobConf { get => currIobConf; } public List CurrIobType { get => currIobType; } /// /// Abilitazione glocale notifiche da conf /// public bool EnableNotify { get => currAppConf.EnableNotify; } public List ListIobAdapters { get; set; } = new List(); public LogLevelIob LogLevel { get => logLevel; set { if (logLevel != value) { logLevel = value; SetIobLogLevel($"{value}"); } } } /// /// Massimo consumo di memoria da conf prima di invocare GC esplicito /// public double MaxMemGc { get => currAppConf.TaskData.MaxMemoryGC; } /// /// Totale processi avviati /// public int NumProcConfig { get => numProcConfig; } /// /// Totale processi running /// public int NumProcRunning { get => numProcRunning; } /// /// Totale processi avviati /// public int NumProcStarted { get => numProcStarted; } /// /// Totale processi avviati /// public int NumTypeConfig { get => numTypeConfig; } public int RefreshPeriod { get => currAppConf.TaskData.TimerFastMSec; set { if (currAppConf.TaskData.TimerFastMSec != value) { // verifico ammissibilità currAppConf.TaskData.TimerFastMSec = value < refPMin ? refPMin : value > refPMax ? refPMax : value; ReportConfigUpd(); } } } /// /// Tempo totale esecuzione ultimo scan /// public double RoundTrip { get => roundTripElaps; } /// /// Dataora prox controlloriavvio automatico /// public DateTime VetoAutoCheck { get => _VetoAutoCheck; } #endregion Public Properties #region Public Methods public void DelayRestart(bool doReset) { _VetoAutoCheck = _VetoAutoCheck < DateTime.Now || doReset ? DateTime.Now : VetoAutoCheck; _VetoAutoCheck = _VetoAutoCheck.AddMinutes(minDelayrestart); ReportConfigUpd(); } public void Dispose() { DoCloseAll(true); } /// /// Se abilitato esegue riavvio e report processi variati /// /// se true esegue anche prima della scadenza veto public void DoAutoRestart(bool doForce) { if (AutoRestartEnabled || doForce) { DoRestartPlcKo(); DoReopenClosed(); } } /// /// Chiude tutti i child /// /// resetta elenco public void DoCloseAll(bool doReset) { CheckRunningChild(); isBusy = true; if (ListIobAdapters.Count > 0) { List listPID = new List(); try { // provo a chiudere tutti 1:1 per pID listPID = ListIobAdapters .Where(x => x.isRunning) .Select(x => x.pID) .ToList(); } catch (Exception exc) { Log.Error($"Eccezione DoCloseAll.01:{Environment.NewLine}{exc}"); } if (listPID.Count > 0) { Parallel.ForEach(listPID, pID => { ForceKillByPID(pID); }); // aspetto 100ms Task.Delay(100); } List listNames = ListIobNames(); if (listNames.Count > 0) { Parallel.ForEach(listNames, prgName => { ForceKillByName(prgName); }); } } isBusy = false; // verifico nuovamente i processi CheckRunningChild(); isBusy = true; List stillRunList = new List(); if (ListIobAdapters.Count > 0) { try { stillRunList = ListIobAdapters .Where(x => x.isRunning) .ToList(); } catch (Exception exc) { Log.Error($"Eccezione DoCloseAll.03:{Environment.NewLine}{exc}"); } } // eventuale chiusura if (stillRunList != null && stillRunList.Count > 0) { foreach (var item in stillRunList) { ForceKillByPID(item.pID); ForceKillByName(item.ExeName); } } // verifico se resettare if (doReset) { // resetto elenco! ListIobAdapters.Clear(); numProcStarted = 0; } // resetto item2rem.Clear(); numProcRunning = 0; isBusy = false; } /// /// Elenco degli EXE Names degli IOB gestiti (x chiamate di cleanup/chiusura) /// /// private List ListIobNames() { List listNames = new List(); if (currIobConf != null && currIobConf.ListTarget != null && currIobConf.ListTarget.Count > 0) { // chiudo per nome SE rimasti listNames = currIobConf .ListTarget .Select(x => x.Value.ExeName) .Where(x => !string.IsNullOrEmpty(x)) .Distinct().ToList(); #if false try { } catch (Exception exc) { Log.Error($"Eccezione DoCloseAll.02:{Environment.NewLine}{exc}"); } #endif } return listNames; } /// /// Apre il child selezionato /// public void DoCloseChild(IobAdapt childReq) { isBusy = true; ForceKillByPID(childReq.pID); isBusy = false; CheckRunningChild(); ReportStatusUpd(); } /// /// Apre tutti i processi child e li registra... /// public void DoOpenAllChild() { isBusy = true; // preventivamente CHIUDO TUTTO per i programmi configurati... var listNames = currIobConf .ListTarget .Select(x => x.Value.ExeName) .Where(x => !string.IsNullOrEmpty(x)) .Distinct().ToList(); Parallel.ForEach(listNames, prgName => { ForceKillByName(prgName); }); Thread.Sleep(100); // avvio i child //Parallel.ForEach(currIobConf.ListIOB, item => //{ // startChildProc(item.Value, item.Key); //}); foreach (var item in currIobConf.ListIOB) { startChildProc(item.Value, item.Key); // attesa tra ogni avvio.. Thread.Sleep(100); } UpdateCounters(); ReportStatusUpd(); isBusy = false; } /// /// Apre il child selezionato /// public void DoOpenChildSel(IobAdapt childReq) { isBusy = true; startChildProc(childReq.TgtName, childReq.CodIOB); UpdateCounters(); ReportStatusUpd(); isBusy = false; } /// /// Legge il file di configurazione APP e poi quello degli IobAdaptConf /// public void DoReloadConfig() { ConfPathApp = Path.Combine(ConfDirBase, AppConfName); if (File.Exists(ConfPathApp)) { string rawData = File.ReadAllText(ConfPathApp); if (!string.IsNullOrEmpty(rawData)) { try { currAppConf = JsonConvert.DeserializeObject(rawData) ?? new AppSettings(); } catch { } } } // sistemo conf IobAdaptConf da gestire if (currAppConf.IobAdapt != null && !string.IsNullOrEmpty(currAppConf.IobAdapt.ConfFile)) { ConfDirIob = Path.Combine(ConfDirBase, currAppConf.IobAdapt.ConfDir); ConfPathIob = Path.Combine(ConfDirIob, currAppConf.IobAdapt.ConfFile); if (File.Exists(ConfPathIob)) { string rawData = File.ReadAllText(ConfPathIob); if (!string.IsNullOrEmpty(rawData)) { try { currIobConf = JsonConvert.DeserializeObject(rawData) ?? new IobManConfig(); TargetIobList = currIobConf.ListTarget; } catch { } } // fix eventuale mancanza BaseArgs nel file raw di conf if (!rawData.Contains("BaseArgs")) { RewriteConfFile(); } } // sistemo eventuali conf x target mancanti... FixMissingTargets(); } currIobType = currIobConf.ListIOB.Select(x => x.Value).Distinct().ToList(); numTypeConfig = currIobType.Count(); numProcConfig = currIobConf.ListIOB.Count(); // leggo altri valori minDelayrestart = currAppConf.GetKVP_Int("DelayTimerRestart", 20); } /// /// Chiudo child che NON comunicano col PLC... /// public void DoRestartPlcKo() { var listNotOk = ListIobAdapters.Where(x => !(x.plcOk)).ToList(); foreach (var item in listNotOk) { DoCloseChild(item); } // ora riapro! foreach (var item in listNotOk) { DoOpenChildSel(item); } } /// /// Riapro child chiusi /// public void DoReopenClosed() { var listClosed = ListIobAdapters.Where(x => !(x.isRunning)).ToList(); foreach (var item in listClosed) { DoOpenChildSel(item); } } /// /// Effettua scansione applicazioni, salva e solleva update /// public async Task DoScan() { Stopwatch sw = new Stopwatch(); sw.Start(); await CheckRunningChildAsync(); ReportStatusUpd(); sw.Stop(); StatCollector.RecordExeData("ACService.DoScan", sw.Elapsed); } /// /// Restituisce conf del target IOB dato nome /// /// /// public TargetConfig GetTargetConf(string codTarget) { TargetConfig answ = new TargetConfig(); if (currIobConf.ListTarget.ContainsKey(codTarget)) { answ = currIobConf.ListTarget[codTarget]; } return answ; } public string IobTgtPath(string codIOB) { string answ = ""; if (!string.IsNullOrEmpty(codIOB)) { if (currIobConf.ListIOB.ContainsKey(codIOB)) { string iobType = currIobConf.ListIOB[codIOB]; if (currIobConf.ListTarget.ContainsKey(iobType)) { var exeName = currIobConf.ListTarget[iobType].ExePath; answ = Path.GetDirectoryName(exeName) ?? exeName; } } } return answ; } public string IobType(string codIOB) { string answ = ""; if (!string.IsNullOrEmpty(codIOB)) { if (currIobConf.ListIOB.ContainsKey(codIOB)) { answ = currIobConf.ListIOB[codIOB]; } } return answ; } /// /// Display di tutte le statistiche collezionate /// public void PrintStats() { foreach (var item in StatCollector.TaskData) { Log.Info($"Exec Stats | {item.Key} x {item.Value.NumRun} | {item.Value.AvgTime.TotalMilliseconds:N3}ms | total: {item.Value.TotalTime.TotalSeconds}s"); } // reset StatCollector.ForceReset(); } /// /// Solleva evento richiesta reboot /// public void RaiseRebootReq() { // sollevo evento if (EA_RebootRequested != null) { EA_RebootRequested?.Invoke(); } } public void ReportStatusUpd() { if (EA_StatusUpdated != null) { EA_StatusUpdated?.Invoke(); } } /// /// Avvio di un child process da parametro ARG /// /// Nome Target EXE /// Args da passare all'exe (IobAdaptConf name da caricare) /// posizione (opzionale) in lista public void startChildProc(string tgtName, string codIob, int indice = -1) { Stopwatch sw = Stopwatch.StartNew(); // da testare x aprire chiudere risorsa... string targetExe = @"C:\Steamware\IOB-WIN-NEXT\IOB-WIN-NEXT.exe";// utils.CRS("targetExe"); if (string.IsNullOrEmpty(targetExe)) { targetExe = Path.Combine(AppContext.BaseDirectory, "Resources", "IOB-WIN-FACADE.exe"); } string currTgtExe = targetExe; string startArg = "MODE=MAN IOB=";// $"{utils.CRS("BaseArg")}{codIob}"; if (TargetIobList.Count > 0) { if (TargetIobList.ContainsKey(tgtName)) { currTgtExe = TargetIobList[tgtName].ExePath; startArg = $"{TargetIobList[tgtName].BaseArgs}{codIob}"; } } // verifico esistenza exe, altrimenti crea copia da IOB-WIN-FACADE if (!File.Exists(currTgtExe)) { // creo folder if (!string.IsNullOrEmpty(currTgtExe)) { string baseExeDir = Path.GetDirectoryName(currTgtExe) ?? ""; if (!string.IsNullOrEmpty(baseExeDir)) { Directory.CreateDirectory(baseExeDir); // creo folder conf.. Directory.CreateDirectory(Path.Combine(baseExeDir, "DATA", "CONF")); // creo file exe! string srcPath = Path.Combine(AppContext.BaseDirectory, "Resources", "IOB-WIN-FACADE.exe"); File.Copy(srcPath, currTgtExe); } } } // avvio processo ProcessStartInfo psi = new ProcessStartInfo { //FileName = targetExe, FileName = currTgtExe, Arguments = startArg, WindowStyle = ProcessWindowStyle.Minimized }; try { //childProc.StartInfo = psi; var p = Process.Start(psi); if (p != null) { // accodo nuovo IobAdaptConf... DateTime adesso = DateTime.Now; var exeName = FileVersionInfo.GetVersionInfo(currTgtExe).FileDescription ?? p.ProcessName; IobAdapt newIob = new IobAdapt(redisConn, codIob, p.Id, exeName, tgtName); // cerco IOB tra quelli esistenti x calcolo posizione... var prevRec = ListIobAdapters.FirstOrDefault(x => x.CodIOB == codIob); if (prevRec != null) { indice = ListIobAdapters.IndexOf(prevRec); } // aggiungo a datasource, se indice -1 aggiungendo e basta, altrimenti alla posizione richiesta... if (indice == -1) { ListIobAdapters.Add(newIob); } else { // rimuovo il vecchio ListIobAdapters.RemoveAt(indice); // inserisco il nuovo... ListIobAdapters.Insert(indice, newIob); } sw.Stop(); Log.Info($"Avviato child process per {codIob} | pid: {p.Id} | {sw.ElapsedMilliseconds}ms"); } } catch (Exception exc) { Log.Error($"Eccezione in startChildProc | codIOB: {codIob} | tgtName: {tgtName}{Environment.NewLine}{exc}"); } } #endregion Public Methods #region Protected Fields /// /// elenco item da rimuovere x check andato male... /// protected static List item2rem = new List(); /// /// Dataora prossima scadenza riavvio automatico /// protected DateTime _VetoAutoCheck = DateTime.Now; protected string ConfDirBase = ""; protected List currIobType = new List(); protected string DeviceName = ""; protected int numProcConfig; protected int numProcRunning; protected int numProcStarted; protected int numTypeConfig; protected double roundTripElaps; /// /// OBj x collezione statistiche /// protected TaskRunStats StatCollector = new TaskRunStats(); #endregion Protected Fields #region Protected Properties protected AppSettings currAppConf { get; set; } = new AppSettings(); protected AppSettings CurrAppConf { get => currAppConf; } protected IobManConfig currIobConf { get; set; } = new IobManConfig(); protected SubLicManager SubLicManager { get; set; } = new SubLicManager(); #endregion Protected Properties #region Protected Methods /// /// Helper copia directory + contenuto /// /// /// protected void CopyDirectory(string sourceDir, string destDir) { // Create the destination directory if it doesn't exist if (!Directory.Exists(destDir)) { Directory.CreateDirectory(destDir); } // copio SOLO SE ho la dir di partenza if (Directory.Exists(sourceDir)) { // Copy all files foreach (var file in Directory.GetFiles(sourceDir)) { string destFile = Path.Combine(destDir, Path.GetFileName(file)); File.Copy(file, destFile, true); } // Copy all subdirectories foreach (var dir in Directory.GetDirectories(sourceDir)) { string destSubDir = Path.Combine(destDir, Path.GetFileName(dir)); CopyDirectory(dir, destSubDir); } } } #endregion Protected Methods #region Private Fields /// /// Classe logger /// private static Logger Log = LogManager.GetCurrentClassLogger(); private string AppConfName = "appsettings.json"; private string confDirIob = ""; /// /// Path file di conf Applicazione /// private string ConfPathApp = ""; /// /// Path file di conf IobAdaptConf /// private string ConfPathIob = ""; /// /// semaforo impegno in fase avvio/chiusura... /// private bool isBusy = false; private LogLevelIob logLevel = LogLevelIob.Info; private int minDelayrestart = 30; /// /// Valore massimo ammesso refresh millisecondi /// private int refPMax = 10000; /// /// Valore minimo ammesso refresh millisecondi /// private int refPMin = 100; /// /// Dizionario applicazioni target da lanciare /// private Dictionary TargetIobList = new Dictionary(); /// /// Ms di attesa x uscita processo (std) /// private int waitForExitMsec = 500; #endregion Private Fields #region Private Properties private bool cloudCallActive { get; set; } = false; private string CodImpiego { get; set; } = ""; /// /// multiplexer Redis /// private ConnectionMultiplexer redisConn { get; set; } = null!; #endregion Private Properties #region Private Methods private bool checkInstance(IobAdapt item, List processList) { bool needRem = false; if (!isBusy) { try { // verifico se non sia già stato segnato x rimozione...) if (item2rem.Find(x => x != null && x.pID == item.pID) != null) { needRem = true; } else { // verifico se esista il processo... if (processList.Count > 0) { var p = processList.FirstOrDefault(pr => pr.Id == item.pID); if (p != null) { needRem = p.HasExited; } else { needRem = true; } } else { needRem = true; } if (needRem) { if (!item2rem.Contains(item)) { item2rem.Add(item); } item.isRunning = false; } else { item.isRunning = true; } } } catch { needRem = true; } } return needRem; } /// /// Verifica se i proc child siano ancora in RUN /// private void CheckRunningChild() { bool needRem = false; if (!isBusy) { Stopwatch sw = Stopwatch.StartNew(); // solo se ho qualocsa... if (TargetIobList.Count > 0 && ListIobAdapters.Count > 0) { ConcurrentBag concList = new ConcurrentBag(); // effettua ricerca 1 proc alla volta bool checkSingle = false; if (checkSingle) { // 2024.12.16 chiamata parallela controllo processi // chiamo in parallelo la ricerca di tutti i TIPI di EXE gestiti... Parallel.ForEach(TargetIobList, item => { // 2020.02.01 passato chiamata specifica x leggere in 1 sola volta elenco processi da nome var tempProcList = Process.GetProcessesByName(item.Key); foreach (var sProc in tempProcList) { concList.Add(sProc); } } ); } else { // 2025.06.04 recupero tutti i processi in un colpo solo var allProcList = Process.GetProcesses(); // ...poi chiamata parallela controllo processi da tutti i TIPI di EXE gestiti... Parallel.ForEach(TargetIobList, item => { // ricerco x nome della targetlist... var tempProcList = allProcList.Where(x => x.ProcessName == item.Key).ToList(); foreach (var sProc in tempProcList) { concList.Add(sProc); } } ); // ciclo controllo var list2check = concList.ToList(); if (list2check != null && list2check.Count > 0) { Parallel.ForEach(ListIobAdapters, item => { needRem = checkInstance(item, list2check); } ); } // li segno spenti... else { foreach (var item in ListIobAdapters) { item.isRunning = false; } } } } sw.Stop(); roundTripElaps = sw.Elapsed.TotalMilliseconds; } UpdateCounters(); } /// /// Verifica se i proc child siano ancora in RUN /// private async Task CheckRunningChildAsync() { bool needRem = false; if (!isBusy) { Stopwatch sw = Stopwatch.StartNew(); // solo se ho qualocsa... if (TargetIobList.Count > 0 && ListIobAdapters.Count > 0) { ConcurrentBag concList = new ConcurrentBag(); // effettua ricerca 1 proc alla volta bool checkSingle = false; if (checkSingle) { // 2024.12.16 chiamata parallela controllo processi // chiamo in parallelo la ricerca di tutti i TIPI di EXE gestiti... Parallel.ForEach(TargetIobList, item => { // 2020.02.01 passato chiamata specifica x leggere in 1 sola volta elenco processi da nome var tempProcList = Process.GetProcessesByName(item.Key); foreach (var sProc in tempProcList) { concList.Add(sProc); } } ); } else { //// 2025.06.04 recupero tutti i processi in un colpo solo //var allProcList = Process.GetProcesses(); // 2025.11.26: tutti i processi ma in modalità asincrona su altro thread var allProcList = await Task.Run(() => Process.GetProcesses()); // ...poi chiamata parallela controllo processi da tutti i TIPI di EXE gestiti... Parallel.ForEach(TargetIobList, item => { // ricerco x nome della targetlist... var tempProcList = allProcList.Where(x => x.ProcessName == item.Key).ToList(); foreach (var sProc in tempProcList) { concList.Add(sProc); } } ); // ciclo controllo var list2check = concList.ToList(); if (list2check != null && list2check.Count > 0) { Parallel.ForEach(ListIobAdapters, item => { needRem = checkInstance(item, list2check); } ); } } } sw.Stop(); roundTripElaps = sw.Elapsed.TotalMilliseconds; StatCollector.RecordExeData("RoundTrip", sw.Elapsed); } UpdateCounters(); } /// /// Elimina contenuto directory /// /// private void DeleteDirectoryContents(string directoryPath) { // recupero info dir DirectoryInfo directory = new DirectoryInfo(directoryPath); // elimina file foreach (FileInfo file in directory.GetFiles()) { file.Delete(); } // elimina ulteriori directory foreach (DirectoryInfo subDirectory in directory.GetDirectories()) { subDirectory.Delete(true); } } private void DoSetupRedis() { string redisConnStr = currAppConf.Redis; redisConn = ConnectionMultiplexer.Connect(redisConnStr); } /// /// Verifica target richiesti e configurati, con sistemazione file conf x mancanti eventuali... /// private void FixMissingTargets() { bool needWrite = false; string baseArgs = currAppConf.GetKVP("BaseArgs"); // verifico tutti i target IOB... foreach (var sIob in currIobConf.ListIOB) { // se mancasse il target lo aggiungo... if (!TargetIobList.ContainsKey(sIob.Value)) { // prendo il primo target list var sTarget = TargetIobList.FirstOrDefault(); // ...e sostituisco... TargetConfig defTgt = new TargetConfig() { ExeName = sIob.Value, ExePath = sTarget.Value.ExePath.Replace(sTarget.Key, sIob.Value), LogDir = sTarget.Value.LogDir.Replace(sTarget.Key, sIob.Value), ConfDir = sTarget.Value.ConfDir.Replace(sTarget.Key, sIob.Value), NLogPath = sTarget.Value.NLogPath.Replace(sTarget.Key, sIob.Value), BaseArgs = baseArgs }; TargetIobList.Add(sIob.Value, defTgt); needWrite = true; } } // 2025.01.08: salvo il file aggiornato... if (needWrite) { RewriteConfFile(); } } /// /// Effettua un force kill dato nome processo /// /// private void ForceKillByName(string nomeProc) { Process[] stillRunningProc = Process.GetProcessesByName(nomeProc); if (stillRunningProc != null) { if (stillRunningProc.Length > 0) { foreach (var item in stillRunningProc) { try { Process p = Process.GetProcessById(item.Id); { if (!p.HasExited) { int closeWaitTime = waitForExitMsec * 8; // se è MAN --> aspetto + a lungo... if (nomeProc.Contains("IOB-MAN")) { closeWaitTime = closeWaitTime * 4; } p.CloseMainWindow(); p.WaitForExit(closeWaitTime); } if (!p.HasExited) { Log.Error($"Process not Exited, 2nd try p.kill()"); p.Kill(); p.WaitForExit(waitForExitMsec); } if (!p.HasExited) { Log.Error($"Process not Killed, 3nd try p.kill()"); p.Kill(); p.WaitForExit(waitForExitMsec * 2); } if (!p.HasExited) { Log.Error($"Process not Killed, 4th try p.kill()"); p.Kill(); } } } catch (Exception exc) { Log.Error($"Errore in fase di kill processo da nome {exc}"); } } } } } /// /// Effettua chiusura processo da pID /// /// private void ForceKillByPID(int pID) { try { using (Process p = Process.GetProcessById(pID)) { int numTry = 5; if (!p.HasExited) { p.CloseMainWindow(); // prova a chiudere gentilmente while (numTry > 0 && !p.HasExited) { Log.Info($"Process {p.Id} not exited, waiting for {waitForExitMsec}ms"); p.WaitForExit(waitForExitMsec); numTry--; } if (!p.HasExited) { Log.Error($"Process {p.Id} not exited, now calling p.Kill()"); p.Kill(); } else { Log.Info("-----------------------------------"); Log.Info($"Process {p.Id} closed!!!"); Log.Info("-----------------------------------"); } } } } catch (ArgumentException) { Log.Warn($"Process with PID {pID} does not exist anymore."); } catch (Exception exc) { Log.Error($"Errore in fase di chiusura processo (pid: {pID}){Environment.NewLine}{exc}"); } } /// /// Esecuzione init configurazione + restart globale (se richiesto) /// /// private void LoadConfAndStart(bool startProc) { int stepLoad = 0; try { Log.Info($"LoadConfAndStart | {stepLoad++:00}"); string startDir = Path.GetDirectoryName(AppContext.BaseDirectory)!; Log.Trace($"LoadConfAndStart starting | startDir: {startDir} | target Framework: {AppContext.TargetFrameworkName}"); ConfDirBase = startDir; // init configurazioni DoReloadConfig(); Log.Info($"LoadConfAndStart | {stepLoad++:00}"); // init servizio Redis monitoring DoSetupRedis(); Log.Trace($"Config setup done | ConfPathApp: {ConfPathApp} | ConfPathIob: {ConfPathIob}"); Log.Info($"LoadConfAndStart | {stepLoad++:00}"); // sistemo log a INFO SetIobLogLevel("INFO"); Log.Trace($"Log set to INFO"); Log.Info($"LoadConfAndStart | {stepLoad++:00}"); if (startProc) { // chiudo eventuali processi in RUN DoCloseAll(false); Log.Info($"LoadConfAndStart | StartProc | {stepLoad++:00}"); // forzo chiusura processi "like" se configurato DoForceCloseByName(); Log.Info($"LoadConfAndStart | StartProc | {stepLoad++:00}"); // avvio i processi... DoOpenAllChild(); Log.Trace($"Child Opened"); Log.Info($"LoadConfAndStart | StartProc | {stepLoad++:00}"); // avvio timers e schedulazioni varie StartScheduler(); Log.Info($"LoadConfAndStart | StartProc | {stepLoad++:00}"); } } catch (Exception exc) { Log.Error($"Error in AppControlService.init:{Environment.NewLine}{exc}"); } Log.Info($"LoadConfAndStart | DONE! | {stepLoad++:00}"); } private void DoForceCloseByName() { if (currAppConf.TaskData.ForceKillName.Count > 0) { ConcurrentBag concList = new ConcurrentBag(); // effettua ricerca processi like se configurato // Get all processes running on the machine Process[] allProcesses = Process.GetProcesses(); foreach (var procName in currAppConf.TaskData.ForceKillName) { // Filter processes whose name starts with "Test" var testProcesses = allProcesses .Where(p => p.ProcessName.StartsWith(procName, StringComparison.OrdinalIgnoreCase)) .ToList(); foreach (var item in testProcesses) { ForceKillByPID(item.Id); } } } } private void ReportConfigUpd() { if (EA_ConfigUpdated != null) { EA_ConfigUpdated?.Invoke(); } } /// /// Esegue riscrittura file di conf da parametri correnti a json /// private void RewriteConfFile() { IobManConfig currIobManConf = new IobManConfig() { ListIOB = currIobConf.ListIOB, ListTarget = TargetIobList }; // serializzo e salvo file! string jsonData = JsonConvert.SerializeObject(currIobManConf, Formatting.Indented); File.WriteAllText(ConfPathIob, jsonData); } /// /// Imposta livello log nei file di conf degli IOB tramite procedura x riscrivere il file conf di NLog /// /// private void SetIobLogLevel(string logReq) { // leggo il file loglevel in resources string tplPath = Path.Combine(ConfDirBase, "Resources", "NLog.template.config"); string rawData = File.ReadAllText(tplPath); // sostituzione livello minimo da selezione rawData = rawData.Replace("{{minLevel}}", logReq); // scrivo conf x SW gestiti foreach (var item in TargetIobList) { if (!File.Exists(item.Value.NLogPath)) { // verifico folder parent... string parentDir = Path.GetDirectoryName(item.Value.NLogPath) ?? ""; if (!string.IsNullOrEmpty(parentDir) && !Directory.Exists(parentDir)) { Directory.CreateDirectory(parentDir); } } File.WriteAllText(item.Value.NLogPath, rawData); } // elimino riferimento al codIOB dalla conf... rawData = rawData.Replace(@"/${var:codIOB:default=0000}", ""); // scrivo conf x programma IOB-MAN string nlogFPath = Path.Combine(ConfDirBase, "NLog.config"); File.WriteAllText(nlogFPath, rawData); } /// /// Avvia schedulatore reboot /// private void StartScheduler() { // avvio lo schedulatore, se abilitato... if (currAppConf.TaskData.AutoRebootEnabled) { var dtReq = currAppConf.TaskData.AutoRebootTSpan; TaskSchedulerService.IntervalInMinutes(dtReq.Hours, dtReq.Minutes, currAppConf.TaskData.AutoRebootMinutes, () => { #if false // vecchia versione reload LoadConfAndStart(true); #endif // esecuzione reboot come da button Reboot RaiseRebootReq(); }); } } private void UpdateCounters() { try { if (ListIobAdapters != null && ListIobAdapters.Count > 0) { numProcStarted = ListIobAdapters.Where(x => x.isRunning).Count(); numProcRunning = ListIobAdapters.Where(x => x.isRunning && x.plcOk && x.iobOnline).Count(); } else { numProcStarted = 0; numProcRunning = 0; } } catch (Exception exc) { Log.Error($"Eccezione in UpdateCounters{Environment.NewLine}{exc}"); } } #endregion Private Methods } }