1729 lines
62 KiB
C#
1729 lines
62 KiB
C#
using MapoSDK;
|
|
using Newtonsoft.Json;
|
|
using RestSharp;
|
|
using RestSharp.Serializers.NewtonsoftJson;
|
|
using SharpCompress.Common;
|
|
using SteamWare.IO;
|
|
using SteamWare.Logger;
|
|
using SteamWare.Scheduler;
|
|
using System;
|
|
using System.Collections.Concurrent;
|
|
using System.Collections.Generic;
|
|
using System.Configuration;
|
|
using System.Diagnostics;
|
|
using System.Drawing;
|
|
using System.IO;
|
|
using System.IO.Compression;
|
|
using System.Linq;
|
|
using System.Runtime.InteropServices;
|
|
using System.Threading;
|
|
using System.Threading.Tasks;
|
|
using System.Web.Hosting;
|
|
using System.Windows.Forms;
|
|
|
|
namespace IOB_MAN
|
|
{
|
|
public partial class IOBManPanel : Form
|
|
{
|
|
#region Public Constructors
|
|
|
|
/// <summary>
|
|
/// Init classe
|
|
/// </summary>
|
|
public IOBManPanel()
|
|
{
|
|
InitializeComponent();
|
|
synchronizationContext = SynchronizationContext.Current;
|
|
|
|
preInit();
|
|
loadConfig();
|
|
|
|
// fix log...
|
|
cbLogLevelMin.SelectedValue = "Info";
|
|
setLogLevel("Info");
|
|
|
|
initTimers();
|
|
initControls();
|
|
updateStatus();
|
|
}
|
|
|
|
#endregion Public Constructors
|
|
|
|
#region Protected Fields
|
|
|
|
/// <summary>
|
|
/// elenco item da rimuovere x check andato male...
|
|
/// </summary>
|
|
protected static List<iobAdapt> item2rem = new List<iobAdapt>();
|
|
|
|
/// <summary>
|
|
/// URL di base x l'API di gestione licenze/file upload
|
|
/// </summary>
|
|
protected string ApiUrl = "";
|
|
|
|
/// <summary>
|
|
/// Ramo applicazione (x update)
|
|
/// </summary>
|
|
protected string branchName = "master";
|
|
|
|
/// <summary>
|
|
/// Counter del timer di base
|
|
/// </summary>
|
|
protected int checkPeriod = 2000;
|
|
|
|
/// <summary>
|
|
/// semaforo check...
|
|
/// </summary>
|
|
protected bool checkRunning = false;
|
|
|
|
/// <summary>
|
|
/// Counter del timer di forceCheck (30 sec, era 5 sec)
|
|
/// </summary>
|
|
protected int forceCheckPeriodMult = 30;
|
|
|
|
/// <summary>
|
|
/// Indica ultimo stato del check di restart...
|
|
/// </summary>
|
|
protected bool lastHlRestart = false;
|
|
|
|
/// <summary>
|
|
/// Totale processi avviati - ULTIMO dato mostrato
|
|
/// </summary>
|
|
protected int lastNumProcAvviati = 0;
|
|
|
|
/// <summary>
|
|
/// Totale processi running - ULTIMO dato mostrato
|
|
/// </summary>
|
|
protected int lastNumProcRunning = 0;
|
|
|
|
/// <summary>
|
|
/// Numero di Lock effettuati con successo
|
|
/// </summary>
|
|
protected int numLockFail = 0;
|
|
|
|
/// <summary>
|
|
/// Numero di lock falliti
|
|
/// </summary>
|
|
protected int numLockSuccess = 0;
|
|
|
|
/// <summary>
|
|
/// Totale processi avviati
|
|
/// </summary>
|
|
protected int numProcAvviati;
|
|
|
|
/// <summary>
|
|
/// Totale processi running
|
|
/// </summary>
|
|
protected int numProcRunning;
|
|
|
|
/// <summary>
|
|
/// Dataora prossima scadenza riavvio automatico
|
|
/// </summary>
|
|
protected DateTime tOutAutocheck = DateTime.Now;
|
|
|
|
/// <summary>
|
|
/// Counter del timer UI
|
|
/// </summary>
|
|
protected int uiPeriod = 250;
|
|
|
|
/// <summary>
|
|
/// Ms di attesa x uscita processo (std)
|
|
/// </summary>
|
|
protected int waitForExitMsec = 250;
|
|
|
|
#endregion Protected Fields
|
|
|
|
#region Protected Properties
|
|
|
|
/// <summary>
|
|
/// URL stringa di UPDATE...
|
|
/// </summary>
|
|
protected string updateUrl
|
|
{
|
|
get
|
|
{
|
|
return string.Format("http://seriate.steamware.net:8083/SWS/MAPO/IOB-MAN/{0}/manifest.xml", branchName);
|
|
}
|
|
}
|
|
|
|
#endregion Protected Properties
|
|
|
|
#region Private Fields
|
|
|
|
private const int SW_SHOWMAXIMIZED = 3;
|
|
|
|
private const int SW_SHOWMINIMIZED = 2;
|
|
|
|
private const int SW_SHOWNORMAL = 1;
|
|
|
|
/// <summary>
|
|
/// Context x sync thread
|
|
/// </summary>
|
|
private readonly SynchronizationContext synchronizationContext;
|
|
|
|
/// <summary>
|
|
/// Oggetto semaforico di lock x check threads
|
|
/// </summary>
|
|
private SemaphoreSlim _sync = new SemaphoreSlim(1);
|
|
|
|
/// <summary>
|
|
/// Oggetto semaforico di lock x UI
|
|
/// </summary>
|
|
private SemaphoreSlim _syncUI = new SemaphoreSlim(1);
|
|
|
|
/// <summary>
|
|
/// Binding source degli elementi gestiti..
|
|
/// </summary>
|
|
private BindingSource ElencoIOB = new BindingSource();
|
|
|
|
/// <summary>
|
|
/// Dizionario IOB (nome IOB + tipo target EXE)
|
|
/// </summary>
|
|
private Dictionary<string, string> IobList = new Dictionary<string, string>();
|
|
|
|
/// <summary>
|
|
/// CodIOB selezionato con right click
|
|
/// </summary>
|
|
private string selCodIob = "";
|
|
|
|
/// <summary>
|
|
/// Path di base data la row corrente selezionata con right click
|
|
/// </summary>
|
|
private string selIobTgtPath = "";
|
|
|
|
/// <summary>
|
|
/// Dizionario applicazioni target da lanciare
|
|
/// </summary>
|
|
private Dictionary<string, TargetConfig> TargetList = new Dictionary<string, TargetConfig>();
|
|
|
|
#endregion Private Fields
|
|
|
|
#region Private Methods
|
|
|
|
[DllImport("user32.dll")]
|
|
private static extern bool ShowWindowAsync(IntPtr hWnd, int nCmdShow);
|
|
|
|
/// <summary>
|
|
/// Apro un child x ogni args specificato
|
|
/// </summary>
|
|
private void apriChild()
|
|
{
|
|
// preventivamente CHIUDO TUTTO per i programmi configurati...
|
|
foreach (var item in TargetList)
|
|
{
|
|
forceKillByName(item.Value.ExeName);
|
|
}
|
|
Thread.Sleep(100);
|
|
// avvio i child
|
|
foreach (var item in IobList)
|
|
{
|
|
startChildProc(item.Value, item.Key);
|
|
}
|
|
numProcAvviati = IobList.Count;
|
|
updateNumRunning();
|
|
}
|
|
|
|
private void apriChildSel()
|
|
{
|
|
// SOLO SE selezionato in dgv...
|
|
if (dgvManagedItems.SelectedRows.Count > 0)
|
|
{
|
|
// ciclo su row selezionate
|
|
foreach (DataGridViewRow riga in dgvManagedItems.SelectedRows)
|
|
{
|
|
var iobRec = ((iobAdapt)ElencoIOB[riga.Index]);
|
|
// verifico che sia già chiuso...
|
|
if (iobRec.isRunning == false)
|
|
{
|
|
startChildProc(iobRec.TgtName, iobRec.CodIOB, riga.Index);
|
|
// rimuovo vecchia riga...
|
|
ElencoIOB.RemoveAt(riga.Index);
|
|
}
|
|
}
|
|
}
|
|
updateNumRunning();
|
|
updateStatus();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Apro un child x fare update con parametro che impedisca avvio IOB
|
|
/// </summary>
|
|
private void apriOneUpdate()
|
|
{
|
|
ProcessStartInfo psi = null;
|
|
|
|
// recupero exe di default...
|
|
string TargetExe = utils.CRS("targetExe");
|
|
if (string.IsNullOrEmpty(TargetExe))
|
|
{
|
|
TargetExe = Path.Combine(Application.StartupPath, "Resources", "Test.bat");
|
|
//TargetExe = $@"{Application.StartupPath}\Resources\Test.bat";
|
|
}
|
|
|
|
// 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();
|
|
}
|
|
}
|
|
updateNumRunning();
|
|
}
|
|
|
|
private void AutoUpdater_ApplicationExitEvent()
|
|
{
|
|
utils.lgInfo("Chiusura IOB-MAN");
|
|
Thread.Sleep(100);
|
|
// chiudo tutto
|
|
closeAllChild(true);
|
|
Thread.Sleep(1000);
|
|
utils.lgInfo("Chiusura Applicazione");
|
|
// attendo 1 sec...
|
|
Thread.Sleep(1000);
|
|
// ESCO!
|
|
Application.Exit();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Chiudo primo processo child (se ce ne sono)
|
|
/// </summary>
|
|
/// <param name="sender"></param>
|
|
/// <param name="e"></param>
|
|
private void btnClose_Click(object sender, EventArgs e)
|
|
{
|
|
chiudiChildSel();
|
|
}
|
|
|
|
private void btnCloseAll_Click(object sender, EventArgs e)
|
|
{
|
|
// chiude tutto
|
|
closeAllChild(false);
|
|
//apriChild();
|
|
updateNumRunning();
|
|
updateStatus();
|
|
}
|
|
|
|
private void btnMaximixeAll_Click(object sender, EventArgs e)
|
|
{
|
|
foreach (iobAdapt item in ElencoIOB.List)
|
|
{
|
|
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}");
|
|
}
|
|
}
|
|
}
|
|
|
|
private void btnMinimizeAll_Click(object sender, EventArgs e)
|
|
{
|
|
foreach (iobAdapt item in ElencoIOB.List)
|
|
{
|
|
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}");
|
|
}
|
|
}
|
|
}
|
|
|
|
private void btnMoreTOut_Click(object sender, EventArgs e)
|
|
{
|
|
tOutAutocheck = tOutAutocheck.AddMinutes(utils.CRI("autoRestartTimeoutMin"));
|
|
}
|
|
|
|
private void btnOpenAll_Click(object sender, EventArgs e)
|
|
{
|
|
// per iscurezza chiudo tutto
|
|
closeAllChild(true);
|
|
Thread.Sleep(1000);
|
|
// lettura conf file...
|
|
loadConfig();
|
|
// apertura
|
|
apriChild();
|
|
updateNumRunning();
|
|
updateStatus();
|
|
}
|
|
|
|
private void btnRestartAll_Click(object sender, EventArgs e)
|
|
{
|
|
// chiude tutto
|
|
closeAllChild(true);
|
|
apriChild();
|
|
updateNumRunning();
|
|
updateStatus();
|
|
}
|
|
|
|
private async void btnSendLog_Click(object sender, EventArgs e)
|
|
{
|
|
// salvo valori button normali
|
|
var stdColor = btnSendLog.BackColor;
|
|
var stdText = btnSendLog.Text;
|
|
// mostro che sto inviando dati...
|
|
btnSendLog.Enabled = false;
|
|
btnSendLog.BackColor = Color.OrangeRed;
|
|
btnSendLog.Text = "fix directory";
|
|
btnSendLog.Refresh();
|
|
// svuoto area temp...
|
|
string fileName = "LogFiles.zip";
|
|
string tempDir = Path.Combine(Application.StartupPath, "temp", "logs");
|
|
string zipPath = Path.Combine(Application.StartupPath, "temp", fileName);
|
|
if (Directory.Exists(tempDir))
|
|
{
|
|
Directory.Delete(tempDir, true);
|
|
}
|
|
// ricreo directory...
|
|
Directory.CreateDirectory(tempDir);
|
|
|
|
// definisco limite temporale alle 21 di 2 gg prima...
|
|
DateTime minDate = DateTime.Today.AddHours(-27);
|
|
|
|
string TargetLogDir = utils.CRS("TargetLogDir");
|
|
string logDir = TargetLogDir;
|
|
if (dgvManagedItems.SelectedRows.Count > 0)
|
|
{
|
|
btnSendLog.Text = "zip start";
|
|
btnSendLog.Refresh();
|
|
// ciclo su row selezionate
|
|
foreach (DataGridViewRow riga in dgvManagedItems.SelectedRows)
|
|
{
|
|
// verifico che sia già chiuso...
|
|
var iobData = (iobAdapt)ElencoIOB[riga.Index];
|
|
// calcolo folder
|
|
string exeName = !string.IsNullOrEmpty(iobData.TgtName) ? iobData.TgtName : "";
|
|
if (TargetList.Count > 0 && TargetList.ContainsKey(exeName))
|
|
{
|
|
logDir = Path.Combine(TargetList[exeName].LogDir, iobData.CodIOB);
|
|
}
|
|
else
|
|
{
|
|
logDir = Path.Combine(TargetLogDir, iobData.CodIOB);
|
|
}
|
|
|
|
// recupero file odierno
|
|
DirectoryInfo dI = new DirectoryInfo(logDir);
|
|
var files = dI.GetFiles().Where(i => i.CreationTime >= minDate);
|
|
|
|
// copio in area temp...
|
|
foreach (var file in files)
|
|
{
|
|
Directory.CreateDirectory(Path.Combine(tempDir, iobData.CodIOB));
|
|
file.CopyTo(Path.Combine(tempDir, iobData.CodIOB, file.Name));
|
|
}
|
|
}
|
|
// creo unico ZIP
|
|
if (File.Exists(zipPath))
|
|
{
|
|
File.Delete(zipPath);
|
|
}
|
|
ZipFile.CreateFromDirectory(tempDir, zipPath);
|
|
btnSendLog.Text = "zip end";
|
|
btnSendLog.Refresh();
|
|
|
|
// ciclo di creazione ticket e upload file
|
|
try
|
|
{
|
|
// client chiamate rest
|
|
var client = new RestClient(ApiUrl);
|
|
client.UseNewtonsoftJson();
|
|
|
|
SupportRequest newSuppReq = new SupportRequest();
|
|
string licensePath = Path.Combine(Application.StartupPath, "CONF", "license.json");
|
|
string rawData = "";
|
|
if (File.Exists(licensePath))
|
|
{
|
|
rawData = File.ReadAllText(licensePath);
|
|
}
|
|
if (!string.IsNullOrEmpty(rawData))
|
|
{
|
|
// fare: composizione richiesta da parametri chiave
|
|
newSuppReq = JsonConvert.DeserializeObject<SupportRequest>(rawData);
|
|
}
|
|
else
|
|
{
|
|
string hostName = utils.machineName;
|
|
string listIP = string.Join(", ", utils.machineIp);
|
|
// genero il ticket
|
|
newSuppReq = new SupportRequest()
|
|
{
|
|
CodApp = "MAPO-IOB-WIN-NEXT",
|
|
CodImp = "",
|
|
CodInst = "SteamWare",
|
|
ContactEmail = "info@steamware.net",
|
|
ContactName = "Default Config",
|
|
ContactPhone = "035-460560",
|
|
MasterKey = "a3BRQz/1B34uvvcDoE/D38ssH/c/KSsjpn39wZsxOVsck9rGnBkF3xfUnj3edYIl",
|
|
ReqBody = $"File Upload - MISSING license file | machine: {utils.machineName} | IP: {listIP}",
|
|
Tipo = TipologiaTicket.FileUpload,
|
|
idxSubLic = 0
|
|
};
|
|
}
|
|
|
|
btnSendLog.Text = "LogSend start";
|
|
btnSendLog.BackColor = Color.DarkOrange;
|
|
btnSendLog.Refresh();
|
|
var ticketReq = new RestRequest("/api/ticket/sendReq", DataFormat.Json).AddJsonBody(newSuppReq);
|
|
var ticketResp = await client.PostAsync<TicketDTO>(ticketReq);
|
|
|
|
// preparo richiesta x upload file
|
|
var fileUploadReq = new RestRequest("/api/filesave/single");
|
|
fileUploadReq.AddParameter("ticketId", ticketResp.idxTicket);
|
|
fileUploadReq.AddFile("file", zipPath);
|
|
|
|
// ... infine INVIA file zip che li contiene...
|
|
//var fileUploadResp = client.Post(fileUploadReq);
|
|
var fileUploadResp = await client.PostAsync<UploadResult>(fileUploadReq);
|
|
btnSendLog.Text = "LogSend end";
|
|
btnSendLog.BackColor = Color.DarkOliveGreen;
|
|
btnSendLog.Refresh();
|
|
|
|
// elimino folder temporanea
|
|
if (Directory.Exists(tempDir))
|
|
{
|
|
Directory.Delete(tempDir, true);
|
|
}
|
|
// elimino il file temporaneo...
|
|
if (File.Exists(zipPath))
|
|
{
|
|
File.Delete(zipPath);
|
|
}
|
|
}
|
|
catch (Exception exc)
|
|
{
|
|
Logging.LogError($"Eccezione in fase gestione REST services{Environment.NewLine}{exc}");
|
|
}
|
|
}
|
|
|
|
btnSendLog.BackColor = stdColor;
|
|
btnSendLog.Text = stdText;
|
|
btnSendLog.Enabled = true;
|
|
}
|
|
|
|
private void btnStartSel_Click(object sender, EventArgs e)
|
|
{
|
|
// riapro child (SOLO SE non era già aperto...)
|
|
apriChildSel();
|
|
}
|
|
|
|
private void cbLogLevelMin_SelectedIndexChanged(object sender, EventArgs e)
|
|
{
|
|
// aggiornato livelo di log --> chiamo procedura x riscrivere il file conf di NLog
|
|
setLogLevel($"{cbLogLevelMin.SelectedItem}");
|
|
}
|
|
|
|
/// <summary>
|
|
/// verifica buttons attivi data selezione su gridview...
|
|
/// </summary>
|
|
private void checkButtons()
|
|
{
|
|
bool selected = (dgvManagedItems.SelectedRows.Count > 0);
|
|
|
|
btnSendLog.Visible = selected;
|
|
btnClose.Visible = selected;
|
|
btnStartSel.Visible = selected;
|
|
}
|
|
|
|
private bool checkIstance(iobAdapt item, List<Process> processList)
|
|
{
|
|
bool needRem;
|
|
// verifico se non sia già stato segnato x rimozione...)
|
|
if (item2rem.Find(x => x.pID == item.pID) != null)
|
|
{
|
|
needRem = true;
|
|
}
|
|
else
|
|
{
|
|
// verifico se esista il processo...
|
|
try
|
|
{
|
|
if (processList.Count > 0)
|
|
{
|
|
Process p = processList.FirstOrDefault(pr => pr.Id == item.pID);
|
|
if (p != null)
|
|
{
|
|
needRem = p.HasExited;
|
|
}
|
|
else
|
|
{
|
|
needRem = true;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
needRem = true;
|
|
}
|
|
}
|
|
catch
|
|
{
|
|
needRem = true;
|
|
}
|
|
if (needRem)
|
|
{
|
|
if (!item2rem.Contains(item))
|
|
{
|
|
item2rem.Add(item);
|
|
}
|
|
item.isRunning = false;
|
|
}
|
|
else
|
|
{
|
|
item.isRunning = true;
|
|
}
|
|
}
|
|
|
|
return needRem;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Controllo periodico dei processi attivi
|
|
/// </summary>
|
|
private async Task checkProcessStatusAsync()
|
|
{
|
|
await _sync.WaitAsync();
|
|
|
|
if (!checkRunning)
|
|
{
|
|
// reset variabili appoggio
|
|
checkRunning = true;
|
|
// eseguo task!
|
|
await Task.Run(() => checkRunningchild());
|
|
updateStatus();
|
|
checkRunning = false;
|
|
}
|
|
else
|
|
{
|
|
utils.lgInfo($"Error: checkRunning: {checkRunning}");
|
|
}
|
|
|
|
_sync.Release();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Verifica se i proc child siano ancora in RUN
|
|
/// </summary>
|
|
private void checkRunningchild()
|
|
{
|
|
IList<iobAdapt> allItems = (IList<iobAdapt>)ElencoIOB.List;
|
|
bool needRem = false;
|
|
ConcurrentBag<Process> concList = new ConcurrentBag<Process>();
|
|
|
|
// 2024.12.16 chiamata parallela controllo processi
|
|
// chiamo in parallelo la ricerca di tutti i TIPI di EXE gestiti...
|
|
Parallel.ForEach(TargetList, 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);
|
|
}
|
|
}
|
|
);
|
|
|
|
// ciclo
|
|
Parallel.ForEach(allItems, item =>
|
|
{
|
|
needRem = checkIstance(item, concList.ToList());
|
|
}
|
|
);
|
|
// aggiorno datagrid!
|
|
dgvManagedItems.Invalidate();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Controllo periodico dei processi DA RIATTIVARE
|
|
/// </summary>
|
|
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;
|
|
}
|
|
}
|
|
}
|
|
updateNumRunning();
|
|
updateStatus();
|
|
}
|
|
|
|
private void chkAutoRestart_CheckedChanged(object sender, EventArgs e)
|
|
{
|
|
// se tolgo autorestart --> imposto NUOVA scadenza x forzare check
|
|
tOutAutocheck = DateTime.Now.AddMinutes(utils.CRI("autoRestartTimeoutMin"));
|
|
txtTOutAutoCheck.Visible = !chkAutoRestart.Checked;
|
|
btnMoreTOut.Visible = !chkAutoRestart.Checked;
|
|
// fa subito controllo riavvio...
|
|
processAutoRestart();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Chiude tutti i child
|
|
/// </summary>
|
|
/// <param name="doReset">resetta elenco</param>
|
|
private void closeAllChild(bool doReset)
|
|
{
|
|
List<iobAdapt> listKilled = new List<iobAdapt>();
|
|
item2rem.Clear();
|
|
foreach (iobAdapt item in ElencoIOB.List)
|
|
{
|
|
item2rem.Add(item);
|
|
}
|
|
// processod a elenco noto
|
|
foreach (var item in item2rem)
|
|
{
|
|
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();
|
|
}
|
|
else
|
|
{
|
|
listKilled.Add(item);
|
|
}
|
|
// indico NON running su datasource
|
|
if (doReset)
|
|
{
|
|
ElencoIOB.Remove(item);
|
|
listKilled.Add(item);
|
|
}
|
|
else
|
|
{
|
|
item.isRunning = false;
|
|
}
|
|
}
|
|
catch (Exception exc)
|
|
{
|
|
Logging.Instance.Error($"Errore in fase di chiusura processo (pid: {item.pID} ) da elenco {exc}");
|
|
}
|
|
}
|
|
// elimino da elenco i killed...
|
|
foreach (var item in listKilled)
|
|
{
|
|
item2rem.Remove(item);
|
|
}
|
|
|
|
// verifico elenco ExeName rimasti attivi
|
|
List<string> listExeRemain = item2rem.Select(x => x.ExeName).Distinct().ToList();
|
|
|
|
// se ce ne fossero...
|
|
if (listExeRemain.Count > 0)
|
|
{
|
|
// elimino x nome...
|
|
foreach (var item in TargetList)
|
|
{
|
|
forceKillByName(item.Key);
|
|
Thread.Sleep(waitForExitMsec / 5);
|
|
forceKillByName(item.Value.ExeName);
|
|
}
|
|
|
|
// cerco processi...
|
|
List<Process> processList = new List<Process>();
|
|
|
|
// 2024.12.16 chiamata parallela controllo processi
|
|
// chiamo in parallelo la ricerca di tutti i TIPI di EXE gestiti...
|
|
Parallel.ForEach(TargetList, item =>
|
|
{
|
|
// 2020.02.01 passato chiamata specifica x leggere in 1 sola volta elenco processi da nome
|
|
var tempProcList = Process.GetProcessesByName(item.Key);
|
|
processList.AddRange(tempProcList.ToList());
|
|
}
|
|
);
|
|
|
|
if (processList.Count > 0)
|
|
{
|
|
// attendo 2 * waitForExitMsec che i processi possano chiudersi gracefully...
|
|
Thread.Sleep(waitForExitMsec * 1);
|
|
foreach (var item in listExeRemain)
|
|
{
|
|
forceKillByName(item);
|
|
}
|
|
// ripeto seconda volta x sicurezza
|
|
Thread.Sleep(waitForExitMsec * 2);
|
|
foreach (var item in listExeRemain)
|
|
{
|
|
forceKillByName(item);
|
|
}
|
|
}
|
|
}
|
|
|
|
// verifico se resettare
|
|
if (doReset)
|
|
{
|
|
// resetto elenco!
|
|
ElencoIOB.Clear();
|
|
numProcAvviati = 0;
|
|
}
|
|
// resetto
|
|
item2rem.Clear();
|
|
numProcRunning = 0;
|
|
// update!
|
|
updateStatus();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Chiude il PID selezionato
|
|
/// </summary>
|
|
/// <param name="Item">Chiude item richiesto</param>
|
|
private void closeSingleChild(iobAdapt item)
|
|
{
|
|
utils.lgInfo($"closeSingleChild | Chiusura processo | IOB: {item.CodIOB} | pid: {item.pID}");
|
|
// rimuovo item
|
|
ElencoIOB.Remove(item);
|
|
try
|
|
{
|
|
Process p = Process.GetProcessById(item.pID);
|
|
p.CloseMainWindow();
|
|
p.WaitForExit(waitForExitMsec);
|
|
if (!p.HasExited)
|
|
{
|
|
utils.lgError($"closeSingleChild | Process not exited, now calling p.Kill()");
|
|
p.Kill();
|
|
}
|
|
}
|
|
catch (Exception exc)
|
|
{
|
|
Logging.Instance.Error($"closeSingleChild | Errore in chiusura processo (pid: {item.pID} ){Environment.NewLine}{exc}");
|
|
}
|
|
updateNumRunning();
|
|
}
|
|
|
|
private void closeTimers()
|
|
{
|
|
MainTimer.Dispose();
|
|
forceCheckTimer.Dispose();
|
|
UI_Timer.Dispose();
|
|
}
|
|
|
|
/// <summary>
|
|
/// DoubleClick su DGV
|
|
/// </summary>
|
|
/// <param name="sender"></param>
|
|
/// <param name="e"></param>
|
|
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])
|
|
{
|
|
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..
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Formattazione celle
|
|
/// </summary>
|
|
/// <param name="sender"></param>
|
|
/// <param name="e"></param>
|
|
private void dgvManagedItems_CellFormatting(object sender, DataGridViewCellFormattingEventArgs e)
|
|
{
|
|
if (this.dgvManagedItems.Columns[e.ColumnIndex].Name == "iobOnline")
|
|
{
|
|
if (e.Value != null)
|
|
{
|
|
bool isOk = false;
|
|
bool.TryParse(e.Value.ToString(), out isOk);
|
|
e.CellStyle.BackColor = isOk ? Color.White : Color.Red;
|
|
}
|
|
}
|
|
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.StartsWith("queueElLen"))
|
|
{
|
|
if (e.Value != null)
|
|
{
|
|
int coda = 0;
|
|
int.TryParse(e.Value.ToString(), out coda);
|
|
e.CellStyle.ForeColor = (coda > 0) ? Color.Red : 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;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Click celle DGV (right)
|
|
/// </summary>
|
|
/// <param name="sender"></param>
|
|
/// <param name="e"></param>
|
|
private void dgvManagedItems_CellMouseClick(object sender, DataGridViewCellMouseEventArgs e)
|
|
{
|
|
if (e.RowIndex >= 0)
|
|
{
|
|
if (e.Button == MouseButtons.Right)
|
|
{
|
|
dgvManagedItems.Rows[e.RowIndex].Selected = true;
|
|
iobAdapt selIobRow = (iobAdapt)ElencoIOB[e.RowIndex];
|
|
// salvo info riga selezionata...
|
|
if (e.RowIndex >= 0)
|
|
{
|
|
selCodIob = selIobRow.CodIOB;
|
|
// cerco da conf...
|
|
if (IobList.ContainsKey(selCodIob))
|
|
{
|
|
string tgtKey = IobList[selCodIob];
|
|
if (TargetList.ContainsKey(tgtKey))
|
|
{
|
|
selIobTgtPath = Path.GetDirectoryName(TargetList[tgtKey].ExePath);
|
|
}
|
|
}
|
|
}
|
|
// You can show a context menu or perform other actions here
|
|
ContextMenu contextMenu = new ContextMenu();
|
|
contextMenu.MenuItems.Add(new MenuItem("Show LOG folder", IobFolderOpenLog));
|
|
contextMenu.MenuItems.Add(new MenuItem("Show CONF folder", IobFolderOpenConf));
|
|
contextMenu.MenuItems.Add(new MenuItem("Show APP folder", IobFolderOpenApp));
|
|
contextMenu.MenuItems.Add(new MenuItem("-"));
|
|
contextMenu.MenuItems.Add(new MenuItem($"Close IOB {selCodIob}", IobCloseSel));
|
|
contextMenu.MenuItems.Add(new MenuItem($"Restart IOB {selCodIob}", IobRestartSel));
|
|
contextMenu.Show(dgvManagedItems, dgvManagedItems.PointToClient(Cursor.Position));
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// predispongo larghezze colonne
|
|
dgvManagedItems.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.AllCells;
|
|
dgvManagedItems.AutoResizeColumns();
|
|
dgvManagedItems.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.None;
|
|
dgvManagedItems.AllowUserToResizeColumns = true;
|
|
}
|
|
}
|
|
|
|
private void dgvManagedItems_SelectionChanged(object sender, EventArgs e)
|
|
{
|
|
checkButtons();
|
|
}
|
|
|
|
private void ElencoIOB_AddingNew(object sender, System.ComponentModel.AddingNewEventArgs e)
|
|
{
|
|
}
|
|
|
|
private void ElencoIOB_ListChanged(object sender, System.ComponentModel.ListChangedEventArgs e)
|
|
{
|
|
updateNumRunning();
|
|
}
|
|
|
|
private void forceCheckTimer_Tick(object sender, EventArgs e)
|
|
{
|
|
if (!checkRunning)
|
|
{
|
|
try
|
|
{
|
|
Task result = Task.Run(() => 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 forceCloseALLToolStripMenuItem_Click(object sender, EventArgs e)
|
|
{
|
|
// per iscurezza chiudo tutto
|
|
closeAllChild(true);
|
|
Thread.Sleep(1000);
|
|
updateStatus();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Effettua un force kill dato nome processo
|
|
/// </summary>
|
|
/// <param name="nomeProc"></param>
|
|
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)
|
|
{
|
|
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;
|
|
|
|
// predispongo larghezze colonne
|
|
dgvManagedItems.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.AllCells;
|
|
dgvManagedItems.AutoResizeColumns();
|
|
dgvManagedItems.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.None;
|
|
dgvManagedItems.AllowUserToResizeColumns = true;
|
|
|
|
utils.lgInfo("Timer started");
|
|
if (utils.CRB("autoStartProc"))
|
|
{
|
|
apriChild();
|
|
utils.lgInfo("Start processi effettuato");
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Inizializzazione timers
|
|
/// </summary>
|
|
private void initTimers()
|
|
{
|
|
MainTimer.Interval = checkPeriod;
|
|
MainTimer.Start();
|
|
UI_Timer.Interval = uiPeriod;
|
|
UI_Timer.Start();
|
|
forceCheckTimer.Interval = checkPeriod * forceCheckPeriodMult;
|
|
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 IobCloseSel(object sender, EventArgs e)
|
|
{
|
|
chiudiChildSel();
|
|
// deselezioni...
|
|
foreach (var item in dgvManagedItems.SelectedRows)
|
|
{
|
|
((DataGridViewRow)item).Selected = false;
|
|
}
|
|
}
|
|
|
|
private void IobFolderOpenApp(object sender, EventArgs e)
|
|
{
|
|
Process.Start("explorer.exe", selIobTgtPath);
|
|
}
|
|
|
|
private void IobFolderOpenConf(object sender, EventArgs e)
|
|
{
|
|
Process.Start("explorer.exe", Path.Combine(selIobTgtPath, "DATA", "CONF"));
|
|
}
|
|
|
|
private void IobFolderOpenLog(object sender, EventArgs e)
|
|
{
|
|
Process.Start("explorer.exe", Path.Combine(selIobTgtPath, "logs", selCodIob));
|
|
}
|
|
|
|
private void IOBManPanel_FormClosing(object sender, FormClosingEventArgs e)
|
|
{
|
|
closeAllChild(true);
|
|
Thread.Sleep(250);
|
|
closeAllChild(true);
|
|
closeTimers();
|
|
}
|
|
|
|
private void IOBManPanel_Shown(object sender, EventArgs e)
|
|
{
|
|
// sistemo larghezze salvando e lasciando libero x utente
|
|
foreach (DataGridViewColumn column in dgvManagedItems.Columns)
|
|
{
|
|
column.AutoSizeMode = DataGridViewAutoSizeColumnMode.AllCells;
|
|
int colw = column.Width; //This is important, otherwise the following line will nullify your previous command
|
|
column.AutoSizeMode = DataGridViewAutoSizeColumnMode.None;
|
|
column.Width = colw; //This is important, otherwise the following line will nullify your previous command
|
|
}
|
|
}
|
|
|
|
private void IobRestartSel(object sender, EventArgs e)
|
|
{
|
|
chiudiChildSel();
|
|
apriChildSel();
|
|
// deselezioni...
|
|
foreach (var item in dgvManagedItems.SelectedRows)
|
|
{
|
|
((DataGridViewRow)item).Selected = false;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Caricamento aprametri x lancio client apps
|
|
/// </summary>
|
|
private void loadArgList()
|
|
{
|
|
TargetList.Clear();
|
|
IobList.Clear();
|
|
// cerco se ho il file conf dei target, altrimenti lo popolo coi valori default "applicativo (legacy mode)
|
|
// in primis cerco SE ESISTA il file json di configurazione parametri avvio
|
|
string confPath = utils.CRS("ConfPath");
|
|
string tgtFName = utils.CRS("TargetConfFile");
|
|
string TargetName = utils.CRS("appNameExt");
|
|
string jsonTgtFName = Path.Combine(Application.StartupPath, confPath, tgtFName);
|
|
// verifico se esista il file richiesto
|
|
if (File.Exists(jsonTgtFName))
|
|
{
|
|
// leggo il file json
|
|
using (StreamReader reader = new StreamReader(jsonTgtFName))
|
|
{
|
|
string rawData = reader.ReadToEnd();
|
|
if (!string.IsNullOrEmpty(rawData))
|
|
{
|
|
TargetList = JsonConvert.DeserializeObject<Dictionary<string, TargetConfig>>(rawData);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
string TargetExe = utils.CRS("targetExe");
|
|
if (string.IsNullOrEmpty(TargetExe))
|
|
{
|
|
TargetExe = Path.Combine(Application.StartupPath, "Resources", "Test.bat");
|
|
}
|
|
string TargetNLogConf = utils.CRS("TargetNLogConf");
|
|
string TargetLogDir = utils.CRS("TargetLogDir");
|
|
|
|
TargetConfig defTgt = new TargetConfig()
|
|
{
|
|
ExePath = TargetExe,
|
|
LogDir = TargetLogDir,
|
|
NLogPath = TargetNLogConf
|
|
};
|
|
TargetList.Add(TargetName, defTgt);
|
|
}
|
|
|
|
// in primis cerco SE ESISTA il file json di configurazione parametri avvio
|
|
string fileName = utils.CRS("ArgsConfFile");
|
|
string jsonFileName = Path.Combine(Application.StartupPath, confPath, fileName);
|
|
// verifico se esista il file richiesto
|
|
if (File.Exists(jsonFileName))
|
|
{
|
|
// leggo il file json
|
|
StreamReader reader = new StreamReader(jsonFileName);
|
|
string jsonData = reader.ReadToEnd();
|
|
if (!string.IsNullOrEmpty(jsonData))
|
|
{
|
|
// se modalità legacy --> deserializzo come lista e aggiungo info...
|
|
if (jsonData.StartsWith("["))
|
|
{
|
|
var rawList = JsonConvert.DeserializeObject<List<string>>(jsonData);
|
|
//IobList = rawList.ToDictionary();
|
|
foreach (var item in rawList)
|
|
{
|
|
IobList.Add(item, TargetName);
|
|
}
|
|
}
|
|
// altrimenti provo a deserializzare come dizionario...
|
|
else
|
|
{
|
|
IobList = JsonConvert.DeserializeObject<Dictionary<string, string>>(jsonData);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// se non lo trovassi --> uso la chaive in web.config e GENERO un nuovo file x prox avvio...
|
|
string ArgsString = utils.CRS("IobList");
|
|
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++)
|
|
{
|
|
IobList.Add($"127.0.0.{i + 1}", TargetName);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
var elenco = ArgsString.Split(',');
|
|
foreach (var item in elenco)
|
|
{
|
|
IobList.Add(item, TargetName);
|
|
}
|
|
}
|
|
// serializzo e salvo file!
|
|
string jsonData = JsonConvert.SerializeObject(IobList);
|
|
File.WriteAllText(jsonFileName, jsonData);
|
|
}
|
|
|
|
// 2024.12.17: salvo il file in formato nuovo... se non esiste...
|
|
string fConfName = utils.CRS("FullConfFile");
|
|
string jsonFName = Path.Combine(Application.StartupPath, confPath, fConfName);
|
|
if (!File.Exists(jsonFName))
|
|
{
|
|
IobManConfig currIobManConf = new IobManConfig()
|
|
{
|
|
ListIOB = IobList,
|
|
ListTarget = TargetList
|
|
};
|
|
// serializzo e salvo file!
|
|
string jsonData = JsonConvert.SerializeObject(currIobManConf, Formatting.Indented);
|
|
File.WriteAllText(jsonFName, jsonData);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Caricamento configurazione
|
|
/// </summary>
|
|
private void loadConfig()
|
|
{
|
|
utils.lgInfo("Start loadConfig");
|
|
waitForExitMsec = utils.CRI("waitForExitMsec");
|
|
checkPeriod = utils.CRI("checkPeriod");
|
|
uiPeriod = utils.CRI("uiPeriod");
|
|
forceCheckPeriodMult = utils.CRI("forceCheckPeriodMult");
|
|
ApiUrl = utils.CRS("ApiUrl");
|
|
|
|
// 2024.12.17: verifico se ho il file unico...
|
|
string confPath = utils.CRS("ConfPath");
|
|
string fConfName = utils.CRS("FullConfFile");
|
|
string jsonFName = Path.Combine(Application.StartupPath, confPath, fConfName);
|
|
// verifico se esista il file richiesto
|
|
if (File.Exists(jsonFName))
|
|
{
|
|
utils.lgInfo($"Loading file {jsonFName}");
|
|
// leggo il file json
|
|
using (StreamReader reader = new StreamReader(jsonFName))
|
|
{
|
|
string rawData = reader.ReadToEnd();
|
|
if (!string.IsNullOrEmpty(rawData))
|
|
{
|
|
IobManConfig currIobManConf = JsonConvert.DeserializeObject<IobManConfig>(rawData);
|
|
TargetList = currIobManConf.ListTarget;
|
|
IobList = currIobManConf.ListIOB;
|
|
|
|
utils.lgInfo($"Config prepared | # target:{TargetList.Count} | # IOB:{IobList.Count}");
|
|
}
|
|
}
|
|
}
|
|
//altrimenti processo alla vecchia maniera...
|
|
else
|
|
{
|
|
utils.lgInfo("Start legacy args loading");
|
|
// caricamento configurazione argomenti di avvio processi
|
|
loadArgList();
|
|
}
|
|
}
|
|
|
|
private void loadConfToolStripMenuItem_Click(object sender, EventArgs e)
|
|
{
|
|
// per iscurezza chiudo tutto
|
|
closeAllChild(true);
|
|
Thread.Sleep(500);
|
|
// lettura conf file...
|
|
loadConfig();
|
|
// apertura
|
|
apriChild();
|
|
updateStatus();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Effettua tutte le verifiche periodiche a timer...
|
|
/// </summary>
|
|
/// <param name="sender"></param>
|
|
/// <param name="e"></param>
|
|
private void MainTimer_Tick(object sender, EventArgs e)
|
|
{
|
|
if (!checkRunning)
|
|
{
|
|
try
|
|
{
|
|
Task result = Task.Run(() => checkProcessStatusAsync());
|
|
result.Wait();
|
|
}
|
|
catch (Exception exc)
|
|
{
|
|
Logging.Instance.Error($"MainTimer_Tick {exc}");
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Chiama apertura + update status...
|
|
/// </summary>
|
|
/// <param name="sender"></param>
|
|
/// <param name="e"></param>
|
|
private void openALLToolStripMenuItem_Click(object sender, EventArgs e)
|
|
{
|
|
}
|
|
|
|
private async Task performBarAdvance()
|
|
{
|
|
await _syncUI.WaitAsync();
|
|
synchronizationContext.Post(new SendOrPostCallback(o =>
|
|
{
|
|
tsProgBar.PerformStep();
|
|
if (tsProgBar.Value >= tsProgBar.Maximum)
|
|
{
|
|
tsProgBar.Value = 0;
|
|
}
|
|
tsProgBar.Invalidate();
|
|
}), "");
|
|
_syncUI.Release();
|
|
}
|
|
|
|
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 = 40;
|
|
tsProgBar.Step = 1;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Effettua processing autorestart
|
|
/// </summary>
|
|
private void processAutoRestart()
|
|
{
|
|
// verifico se ci siano processi (da ARGS LIST) NON running --> li riavvio!
|
|
Dictionary<int, iobAdapt> proc2restart = new Dictionary<int, iobAdapt>();
|
|
int indice = 0;
|
|
foreach (iobAdapt item in ElencoIOB.List)
|
|
{
|
|
// se NON E' running
|
|
if (!item.isRunning)
|
|
{
|
|
// segno da eliminare e riavviare
|
|
utils.lgInfo($"Processo non in running | IOB: {item.CodIOB} | pid: {item.pID}");
|
|
proc2restart.Add(indice, item);
|
|
}
|
|
// se NON comunica da troppo (ultima comunicazione è > 5 minuti fa...)
|
|
else if (!item.plcOk)
|
|
{
|
|
utils.lgInfo($"Processo non in PLC-Online | IOB: {item.CodIOB} | pid: {item.pID}");
|
|
proc2restart.Add(indice, item);
|
|
}
|
|
indice++;
|
|
}
|
|
|
|
// SE abilitato autorestart...
|
|
if (chkAutoRestart.Checked)
|
|
{
|
|
// se ci sono processi da riavviare...
|
|
if (proc2restart.Count > 0)
|
|
{
|
|
foreach (var item in proc2restart)
|
|
{
|
|
ElencoIOB.Remove(item);
|
|
// chiudo!
|
|
closeSingleChild(item.Value);
|
|
}
|
|
foreach (var item in proc2restart)
|
|
{
|
|
// riavvio!
|
|
startChildProc(item.Value.TgtName, item.Value.CodIOB, item.Key);
|
|
}
|
|
// update!
|
|
updateStatus();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// se autorestart scaduto e NON checked --> lo imposto
|
|
if (tOutAutocheck < DateTime.Now)
|
|
{
|
|
// lo riattivo
|
|
chkAutoRestart.Checked = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Effettua chiusura completa + rilettura conf + riavvio
|
|
/// </summary>
|
|
private void reloadConfAndRestart()
|
|
{
|
|
utils.lgInfo("Call reloadConfAndRestart: start full reload");
|
|
// per sicurezza chiudo tutto
|
|
closeAllChild(true);
|
|
Thread.Sleep(500);
|
|
updateStatus();
|
|
// rileggo conf
|
|
loadConfig();
|
|
Thread.Sleep(500);
|
|
// riapro
|
|
apriChild();
|
|
utils.lgInfo("Call reloadConfAndRestart: completed full reload");
|
|
}
|
|
|
|
private void reloadConfRestartToolStripMenuItem_Click(object sender, EventArgs e)
|
|
{
|
|
reloadConfAndRestart();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Chiama Restart (close/start) + update status...
|
|
/// </summary>
|
|
/// <param name="sender"></param>
|
|
/// <param name="e"></param>
|
|
private void restartALLToolStripMenuItem_Click(object sender, EventArgs e)
|
|
{
|
|
// chiude tutto
|
|
closeAllChild(false);
|
|
apriChild();
|
|
updateStatus();
|
|
}
|
|
|
|
private void setLogLevel(string selectedValue)
|
|
{
|
|
// leggo il file loglevel in resources
|
|
string tplPath = Path.Combine(Application.StartupPath, "Resources", "NLog.template.config");
|
|
string rawData = File.ReadAllText(tplPath);
|
|
#if falò
|
|
string rawData = File.ReadAllText($@"{Application.StartupPath}\Resources\NLog.template.config");
|
|
#endif
|
|
|
|
// sostituzione livello minimo da selezione
|
|
rawData = rawData.Replace("{{minLevel}}", selectedValue);
|
|
|
|
// scrivo conf x programma IOB-MAN
|
|
string nlogFPath = Path.Combine(Application.StartupPath, "NLog.config");
|
|
File.WriteAllText(nlogFPath, rawData);
|
|
|
|
// scrivo conf x SW gestiti
|
|
foreach (var item in TargetList)
|
|
{
|
|
if (!File.Exists(item.Value.NLogPath))
|
|
{
|
|
// verifico folder parent...
|
|
string parentDir = Path.GetDirectoryName(item.Value.NLogPath);
|
|
if (!Directory.Exists(parentDir))
|
|
{
|
|
Directory.CreateDirectory(parentDir);
|
|
}
|
|
}
|
|
File.WriteAllText(item.Value.NLogPath, rawData);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Avvio di un child process da parametro ARG
|
|
/// </summary>
|
|
/// <param name="tgtName">Nome Target EXE</param>
|
|
/// <param name="codIob">Args da passare all'exe (IOB name da caricare)</param>
|
|
/// <param name="indice">posizione (opzionale) in lista</param>
|
|
private void startChildProc(string tgtName, string codIob, int indice = -1)
|
|
{
|
|
Stopwatch sw = Stopwatch.StartNew();
|
|
ProcessStartInfo psi = null;
|
|
// da testare x aprire chiudere risorsa...
|
|
string TargetExe = utils.CRS("targetExe");
|
|
if (string.IsNullOrEmpty(TargetExe))
|
|
{
|
|
TargetExe = Path.Combine(Application.StartupPath, "Resources", "Test.bat");
|
|
}
|
|
string currTgtExe = TargetExe;
|
|
if (TargetList.Count > 0)
|
|
{
|
|
if (TargetList.ContainsKey(tgtName))
|
|
{
|
|
currTgtExe = TargetList[tgtName].ExePath;
|
|
}
|
|
}
|
|
psi = new ProcessStartInfo
|
|
{
|
|
//FileName = TargetExe,
|
|
FileName = currTgtExe,
|
|
Arguments = $"{utils.CRS("BaseArg")}{codIob}",
|
|
WindowStyle = ProcessWindowStyle.Minimized
|
|
};
|
|
try
|
|
{
|
|
//childProc.StartInfo = psi;
|
|
Process p = Process.Start(psi);
|
|
|
|
// accodo nuovo IOB...
|
|
DateTime adesso = DateTime.Now;
|
|
iobAdapt newIob = new iobAdapt("", codIob, tgtName);
|
|
#if false
|
|
newIob.redisMan = new RedisIobCache("", codIob, tgtName);
|
|
#endif
|
|
newIob.CodIOB = codIob;
|
|
newIob.TgtName = tgtName;
|
|
//newIob.ExeName = p.ProcessName;
|
|
newIob.ExeName = FileVersionInfo.GetVersionInfo(currTgtExe).FileDescription ?? p.ProcessName;
|
|
//newIob.ExeName = tgtName;
|
|
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);
|
|
}
|
|
sw.Stop();
|
|
utils.lgInfo($"Avviato child process per {codIob} | pid: {p.Id} | {sw.ElapsedMilliseconds}ms");
|
|
}
|
|
catch (Exception exc)
|
|
{
|
|
utils.lgError($"Eccezione in startChildProc | codIOB: {codIob} | tgtName: {tgtName}{Environment.NewLine}{exc}");
|
|
}
|
|
}
|
|
|
|
private void txtTOutAutoCheck_TextChanged(object sender, EventArgs e)
|
|
{
|
|
}
|
|
|
|
private void UI_Timer_Tick(object sender, EventArgs e)
|
|
{
|
|
Task result = updateProgBarAsync();
|
|
result.Wait();
|
|
}
|
|
|
|
private void updateIOBWINToolStripMenuItem_Click(object sender, EventArgs e)
|
|
{
|
|
// chiude tutte
|
|
closeAllChild(true);
|
|
Thread.Sleep(500);
|
|
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(500);
|
|
updateStatus();
|
|
// apre solo 1 con conf "fake" x condurre update...
|
|
apriOneUpdate();
|
|
}
|
|
|
|
private void updateNumRunning()
|
|
{
|
|
// ricalcolo running...
|
|
numProcRunning = 0;
|
|
// ciclo su row selezionate
|
|
foreach (DataGridViewRow riga in dgvManagedItems.Rows)
|
|
{
|
|
// verifico che sia già chiuso...
|
|
if (((iobAdapt)ElencoIOB[riga.Index]).isRunning)
|
|
{
|
|
numProcRunning++;
|
|
}
|
|
}
|
|
}
|
|
|
|
private async Task updateProgBarAsync()
|
|
{
|
|
await performBarAdvance();
|
|
}
|
|
|
|
private void updateStatus()
|
|
{
|
|
synchronizationContext.Post(new SendOrPostCallback(o =>
|
|
{
|
|
// aggiorno SOLO SE sono variati...
|
|
if (lastNumProcAvviati != numProcAvviati || lastNumProcRunning != numProcRunning)
|
|
{
|
|
// aggiorno labels
|
|
tsslNumProc.Text = $"Configurati {IobList.Count} processi | Avviati: {numProcAvviati} | Attivi: {numProcRunning}";
|
|
lastNumProcAvviati = numProcAvviati;
|
|
lastNumProcRunning = numProcRunning;
|
|
}
|
|
bool hlRestart = false;
|
|
// colore da num proc...
|
|
if (numProcRunning == IobList.Count)
|
|
{
|
|
tsslNumProc.ForeColor = Color.Green;
|
|
}
|
|
else if (numProcAvviati < IobList.Count)
|
|
{
|
|
tsslNumProc.ForeColor = Color.DarkRed;
|
|
hlRestart = true;
|
|
}
|
|
else
|
|
{
|
|
tsslNumProc.ForeColor = Color.OrangeRed;
|
|
hlRestart = true;
|
|
}
|
|
// se NON checked aggiorno contatore...
|
|
if (!chkAutoRestart.Checked)
|
|
{
|
|
txtTOutAutoCheck.Text = $"{tOutAutocheck.Subtract(DateTime.Now).TotalSeconds:N0}";
|
|
}
|
|
// se è variato...
|
|
if (hlRestart != lastHlRestart)
|
|
{
|
|
tOutAutocheck = DateTime.Now.AddMinutes(utils.CRI("autoRestartTimeoutMin"));
|
|
lastHlRestart = hlRestart;
|
|
// fix autorestart...
|
|
if (hlRestart)
|
|
{
|
|
chkAutoRestart.ForeColor = System.Drawing.Color.Red;
|
|
chkAutoRestart.Text = "Auto Restart!!!";
|
|
}
|
|
else
|
|
{
|
|
chkAutoRestart.ForeColor = DefaultForeColor;
|
|
chkAutoRestart.Text = "Auto Restart";
|
|
}
|
|
txtTOutAutoCheck.Visible = !chkAutoRestart.Checked;
|
|
btnMoreTOut.Visible = !chkAutoRestart.Checked;
|
|
}
|
|
}), "");
|
|
}
|
|
|
|
#endregion Private Methods
|
|
}
|
|
} |