From 192dc6d67e44411b3f15ef84eb4e9f35fb24dc47 Mon Sep 17 00:00:00 2001 From: "Samuele E. Locatelli" Date: Mon, 30 Nov 2020 17:48:52 +0100 Subject: [PATCH] riorg codice IobMan --- IOB-MAN/IOBManPanel.cs | 2163 ++++++++++++++++++++-------------------- 1 file changed, 1104 insertions(+), 1059 deletions(-) diff --git a/IOB-MAN/IOBManPanel.cs b/IOB-MAN/IOBManPanel.cs index 576d5148..9b58ff9b 100644 --- a/IOB-MAN/IOBManPanel.cs +++ b/IOB-MAN/IOBManPanel.cs @@ -17,1138 +17,1183 @@ using System.Windows.Forms; namespace IOB_MAN { - - public partial class IOBManPanel : Form - { - #region area gestione hide/maximize finestre - - private const int SW_SHOWNORMAL = 1; - private const int SW_SHOWMINIMIZED = 2; - private const int SW_SHOWMAXIMIZED = 3; - [DllImport("user32.dll")] - private static extern bool ShowWindowAsync(IntPtr hWnd, int nCmdShow); - - #endregion - - /// - /// Context x sync thread - /// - private readonly SynchronizationContext synchronizationContext; - /// - /// Totale processi avviati - /// - protected int numProcAvviati; - /// - /// Totale processi running - /// - protected int numProcRunning; - /// - /// Counter del timer di forceCheck - /// - protected int forceCheckPeriod = 5000; - /// - /// Counter del timer di base - /// - protected int checkPeriod = 1000; - /// - /// Counter del timer UI - /// - protected int uiPeriod = 200; - /// - /// Ms di attesa x uscita processo (std) - /// - protected int waitForExitMsec = 250; - /// - /// Elenco ARGS (uno per child da avviare) - /// - public List ArgsList = new List(); - /// - /// Binding source degli elementi gestiti.. - /// - private BindingSource ElencoIOB = new BindingSource(); - /// - /// Path dell'exe da chiamare - /// - protected string TargetExe = ""; - /// - /// Name dell'exe da chiamare - /// - protected string TargetName = ""; - /// - /// Contatore autockeck nativo - /// - protected int tOutAutocheck = 100; - /// - /// semaforo check... - /// - protected bool checkRunning = false; - /// - /// Oggetto locker x evitare problemi timer - /// - private static object _locker = new object(); - /// - /// Init classe - /// - public IOBManPanel() + public partial class IOBManPanel : Form { - InitializeComponent(); - synchronizationContext = SynchronizationContext.Current; - preInit(); - loadConfig(); - initTimers(); - initControls(); - updateStatus(); - } + #region Private Fields - private void initControls() - { - // gestione eventi binding source - ElencoIOB.AddingNew += ElencoIOB_AddingNew; - ElencoIOB.ListChanged += ElencoIOB_ListChanged; - // collego tab a binding - dgvManagedItems.DataSource = ElencoIOB; - utils.lgInfo("Timer started"); - if (utils.CRB("autoStartProc")) - { - apriChild(); - utils.lgInfo("Start processi effettuato"); - } - } + private const int SW_SHOWMAXIMIZED = 3; + private const int SW_SHOWMINIMIZED = 2; + private const int SW_SHOWNORMAL = 1; - /// - /// Inizializzazione timers - /// - private void initTimers() - { - MainTimer.Interval = checkPeriod; - MainTimer.Start(); - UI_Timer.Interval = uiPeriod; - UI_Timer.Start(); - forceCheckTimer.Interval = forceCheckPeriod; - forceCheckTimer.Start(); - // avvio il task con apposita classe Steamware... da 00:30 - int fullRestartHour = memLayer.ML.CRI("fullRestartHour"); - int fullRestartMinute = memLayer.ML.CRI("fullRestartMinute"); - int fullRestartIntervMin = memLayer.ML.CRI("fullRestartIntervMin"); - TaskSched.IntervalInMinutes(fullRestartHour, fullRestartMinute, fullRestartIntervMin, () => + /// + /// Oggetto locker x evitare problemi timer + /// + private static object _locker = new object(); + + /// + /// Context x sync thread + /// + private readonly SynchronizationContext synchronizationContext; + + /// + /// Binding source degli elementi gestiti.. + /// + private BindingSource ElencoIOB = new BindingSource(); + + #endregion Private Fields + + #region Protected Fields + + /// + /// Ramo applicazione (x update) + /// + protected string branchName = "master"; + + /// + /// Counter del timer di base + /// + protected int checkPeriod = 1000; + + /// + /// semaforo check... + /// + protected bool checkRunning = false; + + /// + /// Counter del timer di forceCheck + /// + protected int forceCheckPeriod = 5000; + + /// + /// Totale processi avviati + /// + protected int numProcAvviati; + + /// + /// Totale processi running + /// + protected int numProcRunning; + + /// + /// Path dell'exe da chiamare + /// + protected string TargetExe = ""; + + /// + /// Name dell'exe da chiamare + /// + protected string TargetName = ""; + + /// + /// Contatore autockeck nativo + /// + protected int tOutAutocheck = 100; + + /// + /// Counter del timer UI + /// + protected int uiPeriod = 200; + + /// + /// Ms di attesa x uscita processo (std) + /// + protected int waitForExitMsec = 250; + + #endregion Protected Fields + + #region Public Fields + + /// + /// Elenco ARGS (uno per child da avviare) + /// + public List ArgsList = new List(); + + #endregion Public Fields + + #region Public Constructors + + /// + /// Init classe + /// + public IOBManPanel() { - // eseguo nel contesto di sincronizzazione - synchronizationContext.Post(new SendOrPostCallback(o => - { - // effettuo reload conf e restart - reloadConfAndRestart(); - }), ""); - }); - } - - private void preInit() - { - utils.lgInfo("Starting App"); - lblApp.Text = $"{ConfigurationManager.AppSettings.Get("appName")}"; - lblVers.Text = $" v.{System.Reflection.Assembly.GetExecutingAssembly().GetName().Version}"; - // init prog bar - tsProgBar.Maximum = 100; - tsProgBar.Step = 4; - } - - /// - /// Caricamento configurazione - /// - private void loadConfig() - { - ArgsList.Clear(); - waitForExitMsec = utils.CRI("waitForExitMsec"); - checkPeriod = utils.CRI("checkPeriod"); - uiPeriod = utils.CRI("uiPeriod"); - forceCheckPeriod = utils.CRI("forceCheckPeriod"); - TargetExe = utils.CRS("targetExe"); - TargetName = utils.CRS("appNameExt"); - if (string.IsNullOrEmpty(TargetExe)) - { - //TargetExe = string.Format(@"{0}\Resources\Test.bat", Application.StartupPath); - TargetExe = $@"{Application.StartupPath}\Resources\Test.bat"; - } - utils.lgInfo($"Target exe: {TargetExe}"); - // caricamento configurazione argomenti di avvio processi - loadArgList(); - } - - private void loadArgList() - { - // in primis cerco SE ESISTA il file json di configuraizone parametri avvio - string fileName = utils.CRS("ArgsConfFile"); - string jsonFileName = $"{Application.StartupPath}{fileName}"; - // verifico se esista il file richeisto - if (File.Exists(jsonFileName)) - { - // leggo il file json - StreamReader reader = new StreamReader(jsonFileName); - string jsonData = reader.ReadToEnd(); - if (!string.IsNullOrEmpty(jsonData)) - { - ArgsList = JsonConvert.DeserializeObject>(jsonData); + InitializeComponent(); + synchronizationContext = SynchronizationContext.Current; + preInit(); + loadConfig(); + initTimers(); + initControls(); + updateStatus(); } - } - else - { - // se non lo trovassi --> uso la chaive in web.config e GENERO un nuovo file x prox avvio... - string ArgsString = utils.CRS("ArgsList"); - utils.lgInfo($"Args found: {ArgsString}"); - if (string.IsNullOrEmpty(ArgsString)) + + #endregion Public Constructors + + #region Protected Properties + + /// + /// URL stringa di UPDATE... + /// + protected string updateUrl { - var rand = new Random(); - // ne creo rand (5-15) di default... - for (int i = 0; i < rand.Next(5, 10); i++) - { - ArgsList.Add($"127.0.0.{i + 1}"); - } + get + { + return string.Format("http://seriate.steamware.net:8083/SWS/MAPO/IOB-MAN/{0}/manifest.xml", branchName); + } } - else + + #endregion Protected Properties + + #region Private Methods + + [DllImport("user32.dll")] + private static extern bool ShowWindowAsync(IntPtr hWnd, int nCmdShow); + + /// + /// Apro un child x ogni args specificato + /// + private void apriChild() { - var elenco = ArgsString.Split(','); - foreach (var item in elenco) - { - ArgsList.Add(item); - } + // preventivamente CHIUDO TUTTO + closeAllChild(true); + Thread.Sleep(250); + // avvio i child + foreach (var item in ArgsList) + { + startChildProc(item); + } + numProcAvviati = ArgsList.Count; + numProcRunning = numProcAvviati; } - // serializzo e salvo file! - string jsonData = JsonConvert.SerializeObject(ArgsList); - File.WriteAllText(jsonFileName, jsonData); - } - } - - private void ElencoIOB_ListChanged(object sender, System.ComponentModel.ListChangedEventArgs e) - { - } - - private void ElencoIOB_AddingNew(object sender, System.ComponentModel.AddingNewEventArgs e) - { - updateStatus(); - } - - private void updateStatus() - { - synchronizationContext.Post(new SendOrPostCallback(o => - { - // aggiorno labels - tsslNumProc.Text = $"Configurati {ArgsList.Count} processi | Avviati: {numProcAvviati} | Attivi: {numProcRunning}"; - bool hlRestart = false; - // colore da num proc... - if (numProcRunning == ArgsList.Count) + private void apriChildSel() { - tsslNumProc.ForeColor = Color.Green; + // SOLO SE selezionato in dgv... + if (dgvManagedItems.SelectedRows.Count > 0) + { + // ciclo su row selezionate + foreach (DataGridViewRow riga in dgvManagedItems.SelectedRows) + { + // verifico che sia già chiuso... + if (((iobAdapt)ElencoIOB[riga.Index]).isRunning == false) + { + startChildProc(((iobAdapt)ElencoIOB[riga.Index]).CodIOB, riga.Index); + // rimuovo vecchia riga... + ElencoIOB.RemoveAt(riga.Index); + } + } + } + updateStatus(); } - else if (numProcAvviati < ArgsList.Count) + + /// + /// Apro un child x fare udpate con parametro che impedisca avvio IOB + /// + private void apriOneUpdate() { - tsslNumProc.ForeColor = Color.DarkRed; - hlRestart = true; + ProcessStartInfo psi = null; + + // da testare x aprire chiudere risorsa... + psi = new ProcessStartInfo + { + FileName = TargetExe, + Arguments = "MODE=UPD IOB=NONE", + WindowStyle = ProcessWindowStyle.Normal + }; + + // avvio processo con using... + using (Process p = Process.Start(psi)) + { + p.WaitForExit(); + // ora chiudo current... SE configurato + if (utils.CRB("closeOnChildUpdate")) + { + this.Close(); + } + } } - else + + private void AutoUpdater_ApplicationExitEvent() { - tsslNumProc.ForeColor = Color.OrangeRed; - hlRestart = true; + utils.lgInfo("Chiusura IOB-WIN"); + Thread.Sleep(100); + // chiudo tutto + closeAllChild(true); + Thread.Sleep(1000); + utils.lgInfo("Chiusura Applicazione"); + // attendo 1 sec... + Thread.Sleep(1000); + // ESCO! + Application.Exit(); } - // fix autorestart... - if (hlRestart) + + /// + /// Chiudo primo processo child (se ce ne sono) + /// + /// + /// + private void btnClose_Click(object sender, EventArgs e) { - chkAutoRestart.ForeColor = System.Drawing.Color.Red; - chkAutoRestart.Text = "Auto Restart!!!"; - txtTOutAutoCheck.Visible = true; - btnMoreTOut.Visible = true; - // se NON checked aggiorno contatore... - if (!chkAutoRestart.Checked) - { - tOutAutocheck--; - txtTOutAutoCheck.Text = $"{(tOutAutocheck / (1000 / (utils.CRI("checkPeriod"))))}"; - } + chiudiChildSel(); } - else + + private void btnCloseAll_Click(object sender, EventArgs e) { - chkAutoRestart.ForeColor = DefaultForeColor; - chkAutoRestart.Text = "Auto Restart"; - txtTOutAutoCheck.Visible = false; - btnMoreTOut.Visible = false; + // chiude tutto + closeAllChild(false); + //apriChild(); + updateStatus(); } - }), ""); - } - /// - /// Apro un child x ogni args specificato - /// - private void apriChild() - { - // preventivamente CHIUDO TUTTO - closeAllChild(true); - Thread.Sleep(250); - // avvio i child - foreach (var item in ArgsList) - { - startChildProc(item); - } - numProcAvviati = ArgsList.Count; - numProcRunning = numProcAvviati; - } - /// - /// Avvio di un child process da parametro ARG - /// - /// - /// - private void startChildProc(string procArg, int indice = -1) - { - ProcessStartInfo psi = null; - // da testare x aprire chiudere risorsa... - psi = new ProcessStartInfo - { - FileName = TargetExe, - Arguments = $"{utils.CRS("BaseArg")}{procArg}", - WindowStyle = ProcessWindowStyle.Minimized - }; - - //childProc.StartInfo = psi; - Process p = Process.Start(psi); - - // accodo nuovo IOB... - iobAdapt newIob = new iobAdapt(); - DateTime adesso = DateTime.Now; - newIob.redisMan = new RedisIobCache("", procArg); - newIob.CodIOB = procArg; - newIob.startTime = adesso; - newIob.pID = p.Id; - newIob.isRunning = true; - // aggiungo a datasource, se indice -1 aggiungendo e basta, altrimenti alla posizione richiesta... - if (indice == -1) - { - ElencoIOB.Add(newIob); - } - else - { - ElencoIOB.Insert(indice, newIob); - } - utils.lgInfo($"Avviato child process per {procArg} | pid: {p.Id}"); - } - - /// - /// Apro un child x fare udpate con parametro che impedisca avvio IOB - /// - private void apriOneUpdate() - { - ProcessStartInfo psi = null; - - // da testare x aprire chiudere risorsa... - psi = new ProcessStartInfo - { - FileName = TargetExe, - Arguments = "MODE=UPD IOB=NONE", - WindowStyle = ProcessWindowStyle.Normal - }; - - // avvio processo con using... - using (Process p = Process.Start(psi)) - { - p.WaitForExit(); - // ora chiudo current... SE configurato - if (utils.CRB("closeOnChildUpdate")) + private void btnMaximixeAll_Click(object sender, EventArgs e) { - this.Close(); + foreach (iobAdapt item in ElencoIOB.List) + { + if (item.isRunning) + { + try + { + Process p = Process.GetProcessById(item.pID); + // cerco e chiudo quelli che mi interessano... + var windowsHandle = p.MainWindowHandle; + ShowWindowAsync(windowsHandle, SW_SHOWNORMAL); + } + catch (Exception exc) + { + // errore era già chiuso.. + utils.lgError($"Errore in SHOW windows:{Environment.NewLine}{exc}"); + } + } + } } - } - } - /// - /// Chiudo primo processo child (se ce ne sono) - /// - /// - /// - private void btnClose_Click(object sender, EventArgs e) - { - chiudiChildSel(); - } - private void chiudiChildSel() - { - int pid = -1; - // SOLO SE selezionato in dgv... - if (dgvManagedItems.SelectedRows.Count > 0) - { - - foreach (DataGridViewRow riga in dgvManagedItems.SelectedRows) + private void btnMinimizeAll_Click(object sender, EventArgs e) { - // chiudo! - _ = int.TryParse(riga.Cells["pID"].Value.ToString(), out pid); + foreach (iobAdapt item in ElencoIOB.List) + { + if (item.isRunning) + { + try + { + Process p = Process.GetProcessById(item.pID); + // cerco e chiudo quelli che mi interessano... + var windowsHandle = p.MainWindowHandle; + ShowWindowAsync(windowsHandle, SW_SHOWMINIMIZED); + } + catch (Exception exc) + { + // errore era già chiuso.. + utils.lgError($"Errore in HIDE windows:{Environment.NewLine}{exc}"); + } + } + } + } - if (pid >= 0) - { - // provo a vedere SE ci sia il processo e di conseguenza lo chiudo... + private void btnMoreTOut_Click(object sender, EventArgs e) + { + tOutAutocheck += 60 * utils.CRI("autoRestartTimeoutMin") * (1000 / (utils.CRI("checkPeriod"))); + } + + private void btnOpenAll_Click(object sender, EventArgs e) + { + // per iscurezza chiudo tutto + closeAllChild(true); + Thread.Sleep(1000); + // lettura conf file... + loadConfig(); + // apertura + apriChild(); + updateStatus(); + } + + private void btnRestartAll_Click(object sender, EventArgs e) + { + // chiude tutto + closeAllChild(true); + apriChild(); + updateStatus(); + } + + private void btnStartSel_Click(object sender, EventArgs e) + { + // riapro child (SOLO SE non era già aperto...) + apriChildSel(); + } + + /// + /// verifica buttons attivi data selezione su gridview... + /// + private void checkButtons() + { + bool selected = (dgvManagedItems.SelectedRows.Count > 0); + btnClose.Enabled = selected; + } + + private bool checkIstance(iobAdapt item, List item2rem, Process[] processList) + { + bool needRem; + // verifico se esista il processo... try { - Process p = Process.GetProcessById(pid); - // cerco e chiudo quelli che mi interessano... - p.CloseMainWindow(); + if (processList.Length > 0) + { + Process p = myGetProcByID(processList, item.pID); + needRem = p.HasExited; + } + else + { + needRem = true; + } } catch { - // errore era già chiuso.. + needRem = true; } - // indico NON running su datasource - ((iobAdapt)ElencoIOB[riga.Index]).isRunning = false; - } - } - } - updateStatus(); - } - /// - /// Cerca nell'elenco il processo corrente - /// - /// - /// - /// - public static Process myGetProcByID(Process[] processlist, int id) - { - return processlist.FirstOrDefault(pr => pr.Id == id); - } - - /// - /// Effettua tutte le verifiche periodiche a timer... - /// - /// - /// - private void MainTimer_Tick(object sender, EventArgs e) - { - MainTimer.Stop(); - if (!checkRunning) - { - //checkProcessStatusAsync(); - try - { - Task result = checkProcessStatusAsync(); - result.Wait(); - } - catch (Exception exc) - { - Logging.Instance.Error($"MainTimer_Tick {exc}"); - } - } - MainTimer.Start(); - } - - private void forceCheckTimer_Tick(object sender, EventArgs e) - { - if (!checkRunning) - { - //checkProcessStatusAsync(); - try - { - Task result = checkProcessStatusAsync(); - result.Wait(); - } - catch (Exception exc) - { - Logging.Instance.Error($"forceCheckTimer_Tick {exc}"); - } - } - checkWatchdog(); - // riavvio i timer x sicurezza... - UI_Timer.Stop(); - UI_Timer.Start(); - MainTimer.Stop(); - MainTimer.Start(); - } - private void UI_Timer_Tick(object sender, EventArgs e) - { - UI_Timer.Stop(); - Task result = updateProgBarAsync(); - result.Wait(); - UI_Timer.Start(); - } - /// - /// Controllo periodico dei processi DA RIATTIVARE - /// - private void checkWatchdog() - { - processAutoRestart(); - // aggiorno datagrid! - dgvManagedItems.Invalidate(); - } - /// - /// Effettua processing autorestart - /// - private void processAutoRestart() - { - // verifico se ci siano processi (da ARGS LIST) NON running --> li riavvio! - Dictionary proc2restart = new Dictionary(); - Dictionary proc2close = new Dictionary(); - int indice = 0; - foreach (iobAdapt item in ElencoIOB.List) - { - // se NON comunica da troppo (ultima comunicazione è > 5 minuti fa...) - if (!item.plcOk) - { - proc2close.Add(indice, item); - } - // se NON E' running - if (!item.isRunning) - { - // segno da eliminare e riavviare - proc2restart.Add(indice, item); - } - indice++; - } - - // SE abilitato autorestart... - if (chkAutoRestart.Checked) - { - // in primis processo quelli che non comunicano e mi limito a chiuderli... - foreach (var item in proc2close) - { - ElencoIOB.Remove(item); - utils.lgInfo($"Chiusura processo non in PLC-Online | IOB: {item.Value.CodIOB} | pid: {item.Value.pID}"); - // chiudo! - closeSingleChild(item.Value); - } - foreach (var item in proc2close) - { - // riavvio! - startChildProc(item.Value.CodIOB, item.Key); - } - - // se ho da riavviare... elimino! - foreach (var dictVal in proc2restart) - { - ElencoIOB.Remove(dictVal.Value); - utils.lgInfo($"Chiusura processo non in running | IOB: {dictVal.Value.CodIOB} | pid: {dictVal.Value.pID}"); - } - // li faccio ripartire! - foreach (var item in proc2restart) - { - startChildProc(item.Value.CodIOB, item.Key); - } - - // update! - updateStatus(); - } - else - { - // se autorestart scaduto e NON checked --> lo imposto - if (tOutAutocheck < 0) - { - // lo riattivo - chkAutoRestart.Checked = true; - } - } - } - /// - /// Controllo periodico dei processi attivi - /// - private async Task checkProcessStatusAsync() - { - var hasLock = false; - try - { - Monitor.TryEnter(_locker, ref hasLock); - if (!hasLock) - { - return; - } - if (!checkRunning) - { - // reset variabili appoggio - checkRunning = true; - // eseguo task! - await Task.Run(() => checkRunningchild()).ConfigureAwait(false); - updateStatus(); - checkRunning = false; - } - } - finally - { - if (hasLock) - { - Monitor.Exit(_locker); - } - } - } - - private async Task updateProgBarAsync() - { - await Task.Run(() => performBarAdvance()).ConfigureAwait(false); - } - - private void performBarAdvance() - { - synchronizationContext.Post(new SendOrPostCallback(o => - { - tsProgBar.PerformStep(); - if (tsProgBar.Value >= tsProgBar.Maximum) - { - tsProgBar.Value = 0; - } - tsProgBar.Invalidate(); - }), ""); - } - - /// - /// Verifica se i proc child siano ancora in RUN - /// - private void checkRunningchild() - { - List item2rem = new List(); - IList allItems = (IList)ElencoIOB.List; - bool needRem = false; - - numProcRunning = numProcAvviati; - - // 2020.02.01 passato chiamata specifica x leggere in 1 sola volta TUTTO elenco processi (x nome)... - Process[] processList = Process.GetProcessesByName(TargetName); - - // ciclo - Parallel.ForEach(allItems, item => - { - needRem = checkIstance(item, item2rem, processList); - } - ); - // aggiorno datagrid! - dgvManagedItems.Invalidate(); - } - - private bool checkIstance(iobAdapt item, List item2rem, Process[] processList) - { - bool needRem; - // verifico se esista il processo... - try - { - if (processList.Length > 0) - { - Process p = myGetProcByID(processList, item.pID); - needRem = p.HasExited; - } - else - { - needRem = true; - } - } - catch - { - needRem = true; - } - if (needRem) - { - if (!item2rem.Contains(item)) - { - item2rem.Add(item); - } - item.isRunning = false; - numProcRunning--; - } - else - { - item.isRunning = true; - } - - return needRem; - } - - private void IOBManPanel_FormClosing(object sender, FormClosingEventArgs e) - { - closeAllChild(true); - Thread.Sleep(500); - closeAllChild(true); - closeTimers(); - } - - private void closeTimers() - { - MainTimer.Dispose(); - forceCheckTimer.Dispose(); - UI_Timer.Dispose(); - } - - /// - /// Chiude il PID selezionato - /// - /// Chiude item richiesto - private void closeSingleChild(iobAdapt item) - { - // rimuovo item - ElencoIOB.Remove(item); - try - { - Process p = Process.GetProcessById(item.pID); - p.CloseMainWindow(); - } - catch - { } - } - /// - /// Chiude tutti i child - /// - /// resetta elenco - private void closeAllChild(bool doReset) - { - List item2rem = new List(); - - foreach (iobAdapt item in ElencoIOB.List) - { - item2rem.Add(item); - } - // processod a elenco noto - foreach (var item in item2rem) - { - if (item.isRunning) - { - try - { - Process p = Process.GetProcessById(item.pID); - p.CloseMainWindow(); - p.WaitForExit(waitForExitMsec); - if (!p.HasExited) + if (needRem) { - utils.lgError($"Process not exited, now calling p.Kill()"); - p.Kill(); - } - // indico NON running su datasource - if (doReset) - { - ElencoIOB.Remove(item); + if (!item2rem.Contains(item)) + { + item2rem.Add(item); + } + item.isRunning = false; + numProcRunning--; } else { - item.isRunning = false; + item.isRunning = true; } - } - catch (Exception exc) - { - Logging.Instance.Error($"Errore in fase di chiusura processo (pid: {item.pID} ) da elenco {exc}"); - } + + return needRem; } - } - // attendo 2*waitForExitMsec che i processi possano chiudersi gracefully... - Thread.Sleep(waitForExitMsec * 2); - forceKillByName(TargetName); - // ripeto seconda volta x sicurezza - Thread.Sleep(waitForExitMsec * 4); - forceKillByName(TargetName); - // verifico se resettare - if (doReset) - { - // resetto elenco! - ElencoIOB.Clear(); - numProcAvviati = 0; - } - numProcRunning = 0; - // update! - updateStatus(); - } - /// - /// Effettua un force kill dato nome processo - /// - /// - private void forceKillByName(string nomeProc) - { - Process[] stillRunningProc = Process.GetProcessesByName(nomeProc); - if (stillRunningProc != null) - { - if (stillRunningProc.Length > 0) + + /// + /// Controllo periodico dei processi attivi + /// + private async Task checkProcessStatusAsync() { - foreach (var item in stillRunningProc) - { + var hasLock = false; try { - Process p = Process.GetProcessById(item.Id); - { - if (!p.HasExited) + Monitor.TryEnter(_locker, ref hasLock); + if (!hasLock) { - p.Kill(); - p.WaitForExit(waitForExitMsec); + return; } - if (!p.HasExited) + if (!checkRunning) { - utils.lgError($"Process not Killed, 2nd try p.kill()"); - p.Kill(); - p.WaitForExit(waitForExitMsec * 2); + // reset variabili appoggio + checkRunning = true; + // eseguo task! + await Task.Run(() => checkRunningchild()).ConfigureAwait(false); + updateStatus(); + checkRunning = false; } - if (!p.HasExited) - { - utils.lgError($"Process not Killed, 3th try p.kill()"); - p.Kill(); - } - } } - catch (Exception exc) + finally { - Logging.Instance.Error($"Errore in fase di kill processo da nome {exc}"); + if (hasLock) + { + Monitor.Exit(_locker); + } } - } } - } - } - private void dgvManagedItems_SelectionChanged(object sender, EventArgs e) - { - checkButtons(); - } - /// - /// verifica buttons attivi data selezione su gridview... - /// - private void checkButtons() - { - bool selected = (dgvManagedItems.SelectedRows.Count > 0); - btnClose.Enabled = selected; - } - - private void dgvManagedItems_CellDoubleClick(object sender, DataGridViewCellEventArgs e) - { - // seleziono riga... - int pid = -1; - if (e.RowIndex >= 0) - { - dgvManagedItems.Rows[e.RowIndex].Selected = true; - using (var riga = dgvManagedItems.Rows[e.RowIndex]) + /// + /// Verifica se i proc child siano ancora in RUN + /// + private void checkRunningchild() { - int.TryParse(riga.Cells["pID"].Value.ToString(), out pid); - if (pid >= 0) - { - // provo a vedere SE ci sia il processo e di conseguenza lo chiudo... + List item2rem = new List(); + IList allItems = (IList)ElencoIOB.List; + bool needRem = false; + + numProcRunning = numProcAvviati; + + // 2020.02.01 passato chiamata specifica x leggere in 1 sola volta TUTTO elenco processi (x nome)... + Process[] processList = Process.GetProcessesByName(TargetName); + + // ciclo + Parallel.ForEach(allItems, item => + { + needRem = checkIstance(item, item2rem, processList); + } + ); + // aggiorno datagrid! + dgvManagedItems.Invalidate(); + } + + /// + /// Controllo periodico dei processi DA RIATTIVARE + /// + private void checkWatchdog() + { + processAutoRestart(); + // aggiorno datagrid! + dgvManagedItems.Invalidate(); + } + + private void chiudiChildSel() + { + int pid = -1; + // SOLO SE selezionato in dgv... + if (dgvManagedItems.SelectedRows.Count > 0) + { + foreach (DataGridViewRow riga in dgvManagedItems.SelectedRows) + { + // chiudo! + _ = int.TryParse(riga.Cells["pID"].Value.ToString(), out pid); + + if (pid >= 0) + { + // provo a vedere SE ci sia il processo e di conseguenza lo chiudo... + try + { + Process p = Process.GetProcessById(pid); + // cerco e chiudo quelli che mi interessano... + p.CloseMainWindow(); + } + catch + { + // errore era già chiuso.. + } + // indico NON running su datasource + ((iobAdapt)ElencoIOB[riga.Index]).isRunning = false; + } + } + } + updateStatus(); + } + + private void chkAutoRestart_CheckedChanged(object sender, EventArgs e) + { + // se tolgo autorestart --> imposto NUOVA scadenza x forzare check + tOutAutocheck = 60 * utils.CRI("autoRestartTimeoutMin") * (1000 / (utils.CRI("checkPeriod"))); + // fa subito controllo riavvio... + processAutoRestart(); + } + + /// + /// Chiude tutti i child + /// + /// resetta elenco + private void closeAllChild(bool doReset) + { + List item2rem = new List(); + + foreach (iobAdapt item in ElencoIOB.List) + { + item2rem.Add(item); + } + // processod a elenco noto + foreach (var item in item2rem) + { + if (item.isRunning) + { + try + { + Process p = Process.GetProcessById(item.pID); + p.CloseMainWindow(); + p.WaitForExit(waitForExitMsec); + if (!p.HasExited) + { + utils.lgError($"Process not exited, now calling p.Kill()"); + p.Kill(); + } + // indico NON running su datasource + if (doReset) + { + ElencoIOB.Remove(item); + } + else + { + item.isRunning = false; + } + } + catch (Exception exc) + { + Logging.Instance.Error($"Errore in fase di chiusura processo (pid: {item.pID} ) da elenco {exc}"); + } + } + } + // attendo 2*waitForExitMsec che i processi possano chiudersi gracefully... + Thread.Sleep(waitForExitMsec * 2); + forceKillByName(TargetName); + // ripeto seconda volta x sicurezza + Thread.Sleep(waitForExitMsec * 4); + forceKillByName(TargetName); + // verifico se resettare + if (doReset) + { + // resetto elenco! + ElencoIOB.Clear(); + numProcAvviati = 0; + } + numProcRunning = 0; + // update! + updateStatus(); + } + + /// + /// Chiude il PID selezionato + /// + /// Chiude item richiesto + private void closeSingleChild(iobAdapt item) + { + // rimuovo item + ElencoIOB.Remove(item); try { - Process p = Process.GetProcessById(pid); - // cerco e chiudo quelli che mi interessano... - var windowsHandle = p.MainWindowHandle; - ShowWindowAsync(windowsHandle, SW_SHOWNORMAL); + Process p = Process.GetProcessById(item.pID); + p.CloseMainWindow(); } catch + { } + } + + private void closeTimers() + { + MainTimer.Dispose(); + forceCheckTimer.Dispose(); + UI_Timer.Dispose(); + } + + private void dgvManagedItems_CellDoubleClick(object sender, DataGridViewCellEventArgs e) + { + // seleziono riga... + int pid = -1; + if (e.RowIndex >= 0) { - // errore era già chiuso.. + dgvManagedItems.Rows[e.RowIndex].Selected = true; + using (var riga = dgvManagedItems.Rows[e.RowIndex]) + { + int.TryParse(riga.Cells["pID"].Value.ToString(), out pid); + if (pid >= 0) + { + // provo a vedere SE ci sia il processo e di conseguenza lo chiudo... + try + { + Process p = Process.GetProcessById(pid); + // cerco e chiudo quelli che mi interessano... + var windowsHandle = p.MainWindowHandle; + ShowWindowAsync(windowsHandle, SW_SHOWNORMAL); + } + catch + { + // errore era già chiuso.. + } + } + } } - } } - } - } - private void btnMinimizeAll_Click(object sender, EventArgs e) - { - foreach (iobAdapt item in ElencoIOB.List) - { - if (item.isRunning) + private void dgvManagedItems_CellFormatting(object sender, DataGridViewCellFormattingEventArgs e) { - try - { - Process p = Process.GetProcessById(item.pID); - // cerco e chiudo quelli che mi interessano... - var windowsHandle = p.MainWindowHandle; - ShowWindowAsync(windowsHandle, SW_SHOWMINIMIZED); - } - catch (Exception exc) - { - // errore era già chiuso.. - utils.lgError($"Errore in HIDE windows:{Environment.NewLine}{exc}"); - } + if (this.dgvManagedItems.Columns[e.ColumnIndex].Name == "iobOnline") + { + if (e.Value != null) + { + bool isOk = false; + bool.TryParse(e.Value.ToString(), out isOk); + if (!isOk) + { + e.CellStyle.BackColor = Color.Red; + } + else + { + e.CellStyle.BackColor = Color.White; + } + } + } + else if (this.dgvManagedItems.Columns[e.ColumnIndex].Name == "lastPlcRead") + { + if (e.Value != null) + { + DateTime adesso = DateTime.Now; + DateTime lastRead = adesso.AddMinutes(-60); + DateTime.TryParse(e.Value.ToString(), out lastRead); + if (Math.Abs(adesso.Subtract(lastRead).TotalSeconds) > 180) + { + e.CellStyle.BackColor = Color.Red; + } + else if (Math.Abs(adesso.Subtract(lastRead).TotalSeconds) > 120) + { + e.CellStyle.BackColor = Color.OrangeRed; + } + else if (Math.Abs(adesso.Subtract(lastRead).TotalSeconds) > 60) + { + e.CellStyle.BackColor = Color.Yellow; + } + else if (Math.Abs(adesso.Subtract(lastRead).TotalSeconds) > 15) + { + e.CellStyle.BackColor = Color.YellowGreen; + } + else + { + e.CellStyle.BackColor = Color.White; + } + } + } + else if (this.dgvManagedItems.Columns[e.ColumnIndex].Name == "queueElLen") + { + if (e.Value != null) + { + int coda = 0; + int.TryParse(e.Value.ToString(), out coda); + if (coda > 0) + { + e.CellStyle.ForeColor = Color.Red; + } + else + { + e.CellStyle.ForeColor = Color.Green; + } + } + } + else if (this.dgvManagedItems.Columns[e.ColumnIndex].Name == "queueFlLen") + { + if (e.Value != null) + { + int coda = 0; + int.TryParse(e.Value.ToString(), out coda); + if (coda > 0) + { + e.CellStyle.ForeColor = Color.Red; + } + else + { + e.CellStyle.ForeColor = Color.Green; + } + } + } + else if (this.dgvManagedItems.Columns[e.ColumnIndex].Name == "isRunning") + { + if (e.Value != null) + { + bool isOk = false; + bool.TryParse(e.Value.ToString(), out isOk); + if (!isOk) + { + e.CellStyle.ForeColor = Color.Red; + DataGridViewCellStyle currstyle = dgvManagedItems[0, e.RowIndex].Style; + currstyle.ForeColor = Color.Red; + dgvManagedItems[1, e.RowIndex].Style = currstyle; + dgvManagedItems[2, e.RowIndex].Style = currstyle; + dgvManagedItems[3, e.RowIndex].Style = currstyle; + } + } + } } - } - } - private void btnMaximixeAll_Click(object sender, EventArgs e) - { - foreach (iobAdapt item in ElencoIOB.List) - { - if (item.isRunning) + private void dgvManagedItems_SelectionChanged(object sender, EventArgs e) { - try - { - Process p = Process.GetProcessById(item.pID); - // cerco e chiudo quelli che mi interessano... - var windowsHandle = p.MainWindowHandle; - ShowWindowAsync(windowsHandle, SW_SHOWNORMAL); - } - catch (Exception exc) - { - // errore era già chiuso.. - utils.lgError($"Errore in SHOW windows:{Environment.NewLine}{exc}"); - } + checkButtons(); } - } - } - /// - /// Chiama apertura + update status... - /// - /// - /// - private void openALLToolStripMenuItem_Click(object sender, EventArgs e) - { - } - - - /// - /// Chiama Restart (close/start) + update status... - /// - /// - /// - private void restartALLToolStripMenuItem_Click(object sender, EventArgs e) - { - // chiude tutto - closeAllChild(false); - apriChild(); - updateStatus(); - } - - private void loadConfToolStripMenuItem_Click(object sender, EventArgs e) - { - // per iscurezza chiudo tutto - closeAllChild(true); - Thread.Sleep(1000); - // lettura conf file... - loadConfig(); - // apertura - apriChild(); - updateStatus(); - } - - private void updateModeToolStripMenuItem_Click(object sender, EventArgs e) - { - // chiude tutte - closeAllChild(true); - Thread.Sleep(1000); - updateStatus(); - // apre solo 1 con conf "fake" x condurre update... - apriOneUpdate(); - } - - private void btnCloseAll_Click(object sender, EventArgs e) - { - // chiude tutto - closeAllChild(false); - //apriChild(); - updateStatus(); - } - - private void btnRestartAll_Click(object sender, EventArgs e) - { - // chiude tutto - closeAllChild(true); - apriChild(); - updateStatus(); - } - - - private void btnOpenAll_Click(object sender, EventArgs e) - { - // per iscurezza chiudo tutto - closeAllChild(true); - Thread.Sleep(1000); - // lettura conf file... - loadConfig(); - // apertura - apriChild(); - updateStatus(); - } - /// - /// Ramo applicazione (x update) - /// - protected string branchName = "master"; - /// - /// URL stringa di UPDATE... - /// - protected string updateUrl - { - get - { - return string.Format("http://seriate.steamware.net:8083/SWS/MAPO/IOB-MAN/{0}/manifest.xml", branchName); - } - } - - private void AutoUpdater_ApplicationExitEvent() - { - utils.lgInfo("Chiusura IOB-WIN"); - Thread.Sleep(100); - // chiudo tutto - closeAllChild(true); - Thread.Sleep(1000); - utils.lgInfo("Chiusura Applicazione"); - // attendo 1 sec... - Thread.Sleep(1000); - // ESCO! - Application.Exit(); - } - private void updateIOBWINToolStripMenuItem_Click(object sender, EventArgs e) - { - // chiude tutte - closeAllChild(true); - Thread.Sleep(1000); - updateStatus(); - // apre solo 1 con conf "fake" x condurre update... - apriOneUpdate(); - } - - private void chkAutoRestart_CheckedChanged(object sender, EventArgs e) - { - // se tolgo autorestart --> imposto NUOVA scadenza x forzare check - tOutAutocheck = 60 * utils.CRI("autoRestartTimeoutMin") * (1000 / (utils.CRI("checkPeriod"))); - // fa subito controllo riavvio... - processAutoRestart(); - } - - private void btnMoreTOut_Click(object sender, EventArgs e) - { - tOutAutocheck += 60 * utils.CRI("autoRestartTimeoutMin") * (1000 / (utils.CRI("checkPeriod"))); - } - - private void txtTOutAutoCheck_TextChanged(object sender, EventArgs e) - { - - } - - private void forceCloseALLToolStripMenuItem_Click(object sender, EventArgs e) - { - // per iscurezza chiudo tutto - closeAllChild(true); - Thread.Sleep(1000); - updateStatus(); - } - - private void reloadConfRestartToolStripMenuItem_Click(object sender, EventArgs e) - { - reloadConfAndRestart(); - } - /// - /// Effettua chiusura completa + rilettura conf + riavvio - /// - private void reloadConfAndRestart() - { - // per iscurezza chiudo tutto - closeAllChild(true); - Thread.Sleep(1000); - updateStatus(); - // rileggo conf - loadConfig(); - Thread.Sleep(500); - // riapro - apriChild(); - } - - private void dgvManagedItems_CellFormatting(object sender, DataGridViewCellFormattingEventArgs e) - { - if (this.dgvManagedItems.Columns[e.ColumnIndex].Name == "iobOnline") - { - if (e.Value != null) + private void ElencoIOB_AddingNew(object sender, System.ComponentModel.AddingNewEventArgs e) { - bool isOk = false; - bool.TryParse(e.Value.ToString(), out isOk); - if (!isOk) - { - e.CellStyle.BackColor = Color.Red; - } - else - { - e.CellStyle.BackColor = Color.White; - } + updateStatus(); } - } - else if (this.dgvManagedItems.Columns[e.ColumnIndex].Name == "lastPlcRead") - { - if (e.Value != null) + + private void ElencoIOB_ListChanged(object sender, System.ComponentModel.ListChangedEventArgs e) { - DateTime adesso = DateTime.Now; - DateTime lastRead = adesso.AddMinutes(-60); - DateTime.TryParse(e.Value.ToString(), out lastRead); - if (Math.Abs(adesso.Subtract(lastRead).TotalSeconds) > 180) - { - e.CellStyle.BackColor = Color.Red; - } - else if (Math.Abs(adesso.Subtract(lastRead).TotalSeconds) > 120) - { - e.CellStyle.BackColor = Color.OrangeRed; - } - else if (Math.Abs(adesso.Subtract(lastRead).TotalSeconds) > 60) - { - e.CellStyle.BackColor = Color.Yellow; - } - else if (Math.Abs(adesso.Subtract(lastRead).TotalSeconds) > 15) - { - e.CellStyle.BackColor = Color.YellowGreen; - } - else - { - e.CellStyle.BackColor = Color.White; - } } - } - else if (this.dgvManagedItems.Columns[e.ColumnIndex].Name == "queueElLen") - { - if (e.Value != null) + + private void forceCheckTimer_Tick(object sender, EventArgs e) { - int coda = 0; - int.TryParse(e.Value.ToString(), out coda); - if (coda > 0) - { - e.CellStyle.ForeColor = Color.Red; - } - else - { - e.CellStyle.ForeColor = Color.Green; - } + if (!checkRunning) + { + //checkProcessStatusAsync(); + try + { + Task result = checkProcessStatusAsync(); + result.Wait(); + } + catch (Exception exc) + { + Logging.Instance.Error($"forceCheckTimer_Tick {exc}"); + } + } + checkWatchdog(); + // riavvio i timer x sicurezza... + UI_Timer.Stop(); + UI_Timer.Start(); + MainTimer.Stop(); + MainTimer.Start(); } - } - else if (this.dgvManagedItems.Columns[e.ColumnIndex].Name == "queueFlLen") - { - if (e.Value != null) + + private void forceCloseALLToolStripMenuItem_Click(object sender, EventArgs e) { - int coda = 0; - int.TryParse(e.Value.ToString(), out coda); - if (coda > 0) - { - e.CellStyle.ForeColor = Color.Red; - } - else - { - e.CellStyle.ForeColor = Color.Green; - } + // per iscurezza chiudo tutto + closeAllChild(true); + Thread.Sleep(1000); + updateStatus(); } - } - else if (this.dgvManagedItems.Columns[e.ColumnIndex].Name == "isRunning") - { - if (e.Value != null) + + /// + /// Effettua un force kill dato nome processo + /// + /// + private void forceKillByName(string nomeProc) { - bool isOk = false; - bool.TryParse(e.Value.ToString(), out isOk); - if (!isOk) - { - e.CellStyle.ForeColor = Color.Red; - DataGridViewCellStyle currstyle = dgvManagedItems[0, e.RowIndex].Style; - currstyle.ForeColor = Color.Red; - dgvManagedItems[1, e.RowIndex].Style = currstyle; - dgvManagedItems[2, e.RowIndex].Style = currstyle; - dgvManagedItems[3, e.RowIndex].Style = currstyle; - } + 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) + { + p.Kill(); + p.WaitForExit(waitForExitMsec); + } + if (!p.HasExited) + { + utils.lgError($"Process not Killed, 2nd try p.kill()"); + p.Kill(); + p.WaitForExit(waitForExitMsec * 2); + } + if (!p.HasExited) + { + utils.lgError($"Process not Killed, 3th try p.kill()"); + p.Kill(); + } + } + } + catch (Exception exc) + { + Logging.Instance.Error($"Errore in fase di kill processo da nome {exc}"); + } + } + } + } } - } + + private void initControls() + { + // gestione eventi binding source + ElencoIOB.AddingNew += ElencoIOB_AddingNew; + ElencoIOB.ListChanged += ElencoIOB_ListChanged; + // collego tab a binding + dgvManagedItems.DataSource = ElencoIOB; + utils.lgInfo("Timer started"); + if (utils.CRB("autoStartProc")) + { + apriChild(); + utils.lgInfo("Start processi effettuato"); + } + } + + /// + /// Inizializzazione timers + /// + private void initTimers() + { + MainTimer.Interval = checkPeriod; + MainTimer.Start(); + UI_Timer.Interval = uiPeriod; + UI_Timer.Start(); + forceCheckTimer.Interval = forceCheckPeriod; + forceCheckTimer.Start(); + // avvio il task con apposita classe Steamware... da 00:30 + int fullRestartHour = memLayer.ML.CRI("fullRestartHour"); + int fullRestartMinute = memLayer.ML.CRI("fullRestartMinute"); + int fullRestartIntervMin = memLayer.ML.CRI("fullRestartIntervMin"); + TaskSched.IntervalInMinutes(fullRestartHour, fullRestartMinute, fullRestartIntervMin, () => + { + // eseguo nel contesto di sincronizzazione + synchronizationContext.Post(new SendOrPostCallback(o => + { + // effettuo reload conf e restart + reloadConfAndRestart(); + }), ""); + }); + } + + private void IOBManPanel_FormClosing(object sender, FormClosingEventArgs e) + { + closeAllChild(true); + Thread.Sleep(500); + closeAllChild(true); + closeTimers(); + } + + private void loadArgList() + { + // in primis cerco SE ESISTA il file json di configuraizone parametri avvio + string fileName = utils.CRS("ArgsConfFile"); + string jsonFileName = $"{Application.StartupPath}{fileName}"; + // verifico se esista il file richeisto + if (File.Exists(jsonFileName)) + { + // leggo il file json + StreamReader reader = new StreamReader(jsonFileName); + string jsonData = reader.ReadToEnd(); + if (!string.IsNullOrEmpty(jsonData)) + { + ArgsList = JsonConvert.DeserializeObject>(jsonData); + } + } + else + { + // se non lo trovassi --> uso la chaive in web.config e GENERO un nuovo file x prox avvio... + string ArgsString = utils.CRS("ArgsList"); + utils.lgInfo($"Args found: {ArgsString}"); + if (string.IsNullOrEmpty(ArgsString)) + { + var rand = new Random(); + // ne creo rand (5-15) di default... + for (int i = 0; i < rand.Next(5, 10); i++) + { + ArgsList.Add($"127.0.0.{i + 1}"); + } + } + else + { + var elenco = ArgsString.Split(','); + foreach (var item in elenco) + { + ArgsList.Add(item); + } + } + // serializzo e salvo file! + string jsonData = JsonConvert.SerializeObject(ArgsList); + File.WriteAllText(jsonFileName, jsonData); + } + } + + /// + /// Caricamento configurazione + /// + private void loadConfig() + { + ArgsList.Clear(); + waitForExitMsec = utils.CRI("waitForExitMsec"); + checkPeriod = utils.CRI("checkPeriod"); + uiPeriod = utils.CRI("uiPeriod"); + forceCheckPeriod = utils.CRI("forceCheckPeriod"); + TargetExe = utils.CRS("targetExe"); + TargetName = utils.CRS("appNameExt"); + if (string.IsNullOrEmpty(TargetExe)) + { + //TargetExe = string.Format(@"{0}\Resources\Test.bat", Application.StartupPath); + TargetExe = $@"{Application.StartupPath}\Resources\Test.bat"; + } + utils.lgInfo($"Target exe: {TargetExe}"); + // caricamento configurazione argomenti di avvio processi + loadArgList(); + } + + private void loadConfToolStripMenuItem_Click(object sender, EventArgs e) + { + // per iscurezza chiudo tutto + closeAllChild(true); + Thread.Sleep(1000); + // lettura conf file... + loadConfig(); + // apertura + apriChild(); + updateStatus(); + } + + /// + /// Effettua tutte le verifiche periodiche a timer... + /// + /// + /// + private void MainTimer_Tick(object sender, EventArgs e) + { + MainTimer.Stop(); + if (!checkRunning) + { + //checkProcessStatusAsync(); + try + { + Task result = checkProcessStatusAsync(); + result.Wait(); + } + catch (Exception exc) + { + Logging.Instance.Error($"MainTimer_Tick {exc}"); + } + } + MainTimer.Start(); + } + + /// + /// Chiama apertura + update status... + /// + /// + /// + private void openALLToolStripMenuItem_Click(object sender, EventArgs e) + { + } + + private void performBarAdvance() + { + synchronizationContext.Post(new SendOrPostCallback(o => + { + tsProgBar.PerformStep(); + if (tsProgBar.Value >= tsProgBar.Maximum) + { + tsProgBar.Value = 0; + } + tsProgBar.Invalidate(); + }), ""); + } + + private void preInit() + { + utils.lgInfo("Starting App"); + lblApp.Text = $"{ConfigurationManager.AppSettings.Get("appName")}"; + lblVers.Text = $" v.{System.Reflection.Assembly.GetExecutingAssembly().GetName().Version}"; + // init prog bar + tsProgBar.Maximum = 100; + tsProgBar.Step = 4; + } + + /// + /// Effettua processing autorestart + /// + private void processAutoRestart() + { + // verifico se ci siano processi (da ARGS LIST) NON running --> li riavvio! + Dictionary proc2restart = new Dictionary(); + Dictionary proc2close = new Dictionary(); + int indice = 0; + foreach (iobAdapt item in ElencoIOB.List) + { + // se NON comunica da troppo (ultima comunicazione è > 5 minuti fa...) + if (!item.plcOk) + { + proc2close.Add(indice, item); + } + // se NON E' running + if (!item.isRunning) + { + // segno da eliminare e riavviare + proc2restart.Add(indice, item); + } + indice++; + } + + // SE abilitato autorestart... + if (chkAutoRestart.Checked) + { + // in primis processo quelli che non comunicano e mi limito a chiuderli... + foreach (var item in proc2close) + { + ElencoIOB.Remove(item); + utils.lgInfo($"Chiusura processo non in PLC-Online | IOB: {item.Value.CodIOB} | pid: {item.Value.pID}"); + // chiudo! + closeSingleChild(item.Value); + } + foreach (var item in proc2close) + { + // riavvio! + startChildProc(item.Value.CodIOB, item.Key); + } + + // se ho da riavviare... elimino! + foreach (var dictVal in proc2restart) + { + ElencoIOB.Remove(dictVal.Value); + utils.lgInfo($"Chiusura processo non in running | IOB: {dictVal.Value.CodIOB} | pid: {dictVal.Value.pID}"); + } + // li faccio ripartire! + foreach (var item in proc2restart) + { + startChildProc(item.Value.CodIOB, item.Key); + } + + // update! + updateStatus(); + } + else + { + // se autorestart scaduto e NON checked --> lo imposto + if (tOutAutocheck < 0) + { + // lo riattivo + chkAutoRestart.Checked = true; + } + } + } + + /// + /// Effettua chiusura completa + rilettura conf + riavvio + /// + private void reloadConfAndRestart() + { + // per sicurezza chiudo tutto + closeAllChild(true); + Thread.Sleep(1000); + updateStatus(); + // rileggo conf + loadConfig(); + Thread.Sleep(500); + // riapro + apriChild(); + } + + private void reloadConfRestartToolStripMenuItem_Click(object sender, EventArgs e) + { + reloadConfAndRestart(); + } + + /// + /// Chiama Restart (close/start) + update status... + /// + /// + /// + private void restartALLToolStripMenuItem_Click(object sender, EventArgs e) + { + // chiude tutto + closeAllChild(false); + apriChild(); + updateStatus(); + } + + /// + /// Avvio di un child process da parametro ARG + /// + /// + /// + private void startChildProc(string procArg, int indice = -1) + { + ProcessStartInfo psi = null; + // da testare x aprire chiudere risorsa... + psi = new ProcessStartInfo + { + FileName = TargetExe, + Arguments = $"{utils.CRS("BaseArg")}{procArg}", + WindowStyle = ProcessWindowStyle.Minimized + }; + + //childProc.StartInfo = psi; + Process p = Process.Start(psi); + + // accodo nuovo IOB... + iobAdapt newIob = new iobAdapt(); + DateTime adesso = DateTime.Now; + newIob.redisMan = new RedisIobCache("", procArg); + newIob.CodIOB = procArg; + newIob.startTime = adesso; + newIob.pID = p.Id; + newIob.isRunning = true; + // aggiungo a datasource, se indice -1 aggiungendo e basta, altrimenti alla posizione richiesta... + if (indice == -1) + { + ElencoIOB.Add(newIob); + } + else + { + ElencoIOB.Insert(indice, newIob); + } + utils.lgInfo($"Avviato child process per {procArg} | pid: {p.Id}"); + } + + private void txtTOutAutoCheck_TextChanged(object sender, EventArgs e) + { + } + + private void UI_Timer_Tick(object sender, EventArgs e) + { + UI_Timer.Stop(); + Task result = updateProgBarAsync(); + result.Wait(); + UI_Timer.Start(); + } + + private void updateIOBWINToolStripMenuItem_Click(object sender, EventArgs e) + { + // chiude tutte + closeAllChild(true); + Thread.Sleep(1000); + updateStatus(); + // apre solo 1 con conf "fake" x condurre update... + apriOneUpdate(); + } + + private void updateModeToolStripMenuItem_Click(object sender, EventArgs e) + { + // chiude tutte + closeAllChild(true); + Thread.Sleep(1000); + updateStatus(); + // apre solo 1 con conf "fake" x condurre update... + apriOneUpdate(); + } + + private async Task updateProgBarAsync() + { + await Task.Run(() => performBarAdvance()).ConfigureAwait(false); + } + + private void updateStatus() + { + synchronizationContext.Post(new SendOrPostCallback(o => + { + // aggiorno labels + tsslNumProc.Text = $"Configurati {ArgsList.Count} processi | Avviati: {numProcAvviati} | Attivi: {numProcRunning}"; + bool hlRestart = false; + // colore da num proc... + if (numProcRunning == ArgsList.Count) + { + tsslNumProc.ForeColor = Color.Green; + } + else if (numProcAvviati < ArgsList.Count) + { + tsslNumProc.ForeColor = Color.DarkRed; + hlRestart = true; + } + else + { + tsslNumProc.ForeColor = Color.OrangeRed; + hlRestart = true; + } + // fix autorestart... + if (hlRestart) + { + chkAutoRestart.ForeColor = System.Drawing.Color.Red; + chkAutoRestart.Text = "Auto Restart!!!"; + txtTOutAutoCheck.Visible = true; + btnMoreTOut.Visible = true; + // se NON checked aggiorno contatore... + if (!chkAutoRestart.Checked) + { + tOutAutocheck--; + txtTOutAutoCheck.Text = $"{(tOutAutocheck / (1000 / (utils.CRI("checkPeriod"))))}"; + } + } + else + { + chkAutoRestart.ForeColor = DefaultForeColor; + chkAutoRestart.Text = "Auto Restart"; + txtTOutAutoCheck.Visible = false; + btnMoreTOut.Visible = false; + } + }), ""); + } + + #endregion Private Methods + + #region Public Methods + + /// + /// Cerca nell'elenco il processo corrente + /// + /// + /// + /// + public static Process myGetProcByID(Process[] processlist, int id) + { + return processlist.FirstOrDefault(pr => pr.Id == id); + } + + #endregion Public Methods } - - private void btnStartSel_Click(object sender, EventArgs e) - { - // riapro child (SOLO SE non era già aperto...) - apriChildSel(); - } - - - private void apriChildSel() - { - // SOLO SE selezionato in dgv... - if (dgvManagedItems.SelectedRows.Count > 0) - { - // ciclo su row selezionate - foreach (DataGridViewRow riga in dgvManagedItems.SelectedRows) - { - // verifico che sia già chiuso... - if (((iobAdapt)ElencoIOB[riga.Index]).isRunning == false) - { - startChildProc(((iobAdapt)ElencoIOB[riga.Index]).CodIOB, riga.Index); - // rimuovo vecchia riga... - ElencoIOB.RemoveAt(riga.Index); - } - } - } - updateStatus(); - } - } - -} +} \ No newline at end of file