1213 lines
43 KiB
C#
1213 lines
43 KiB
C#
using DeviceId;
|
|
using EgwControlCenter.Core.DTO;
|
|
using EgwControlCenter.Core.Models;
|
|
using EgwCoreLib.Utils;
|
|
using Newtonsoft.Json;
|
|
using NLog;
|
|
using System.Diagnostics;
|
|
using System.IO.Compression;
|
|
using System.Reflection;
|
|
using System.Threading.Tasks;
|
|
|
|
namespace EgwControlCenter.Core
|
|
{
|
|
public class AppControlService : IAppControlService
|
|
{
|
|
#region Public Fields
|
|
|
|
/// <summary>
|
|
/// Dizionario completo info macchina
|
|
/// </summary>
|
|
public static Dictionary<string, string> DictMachineInfo = new Dictionary<string, string>();
|
|
|
|
/// <summary>
|
|
/// Dizionario completo info networking
|
|
/// </summary>
|
|
public static Dictionary<string, string> DictNetInfo = new Dictionary<string, string>();
|
|
|
|
/// <summary>
|
|
/// Dizionario completo info utente
|
|
/// </summary>
|
|
public static Dictionary<string, string> DictUserInfo = new Dictionary<string, string>();
|
|
|
|
#endregion Public Fields
|
|
|
|
#region Public Constructors
|
|
|
|
public AppControlService()
|
|
{
|
|
try
|
|
{
|
|
Assembly assembly = Assembly.GetExecutingAssembly();
|
|
string startDir = Path.GetDirectoryName(assembly.Location)!;
|
|
ConfDir = startDir;
|
|
CodImpiego = SLicManager.CodImpiego();
|
|
// setup RuntimConf (da gestire anche con set remoto...)
|
|
RuntimeConfDict.Add("CountNumFastCheck", "60");
|
|
// chiedo info x fare setup DeviceName...
|
|
var allInfo = DeviceInfoDict();
|
|
DeviceName = DictUserInfo != null && DictUserInfo.ContainsKey("MachineName") ? DictUserInfo["MachineName"] : "UnkDevice";
|
|
//DataDir = Environment.GetEnvironmentVariable("ClickOnce_DataDirectory") ?? startDir;
|
|
string appData = Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData);
|
|
if (string.IsNullOrEmpty(appData))
|
|
{
|
|
appData = "C:\\ProgramData";
|
|
}
|
|
DataDir = Path.Combine(appData, "EgalWare", "AppControlCenter");
|
|
Log.Trace($"appData: {appData} | EnvData: {Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData)}");
|
|
// verifico esistenza directory...
|
|
Directory.CreateDirectory(DataDir);
|
|
CurrCheck = new ReleaseChecker(ConfDir, DataDir);
|
|
Log.Trace($"Folder Setup | {ConfDir} | {DataDir}");
|
|
}
|
|
catch (Exception exc)
|
|
{
|
|
Log.Error($"Error in AppControlService.init:{Environment.NewLine}{exc}");
|
|
}
|
|
}
|
|
|
|
#endregion Public Constructors
|
|
|
|
#region Public Events
|
|
|
|
/// <summary>
|
|
/// Evento update configurazione
|
|
/// </summary>
|
|
public event Action EA_ConfigUpdated = null!;
|
|
|
|
/// <summary>
|
|
/// Evento richiesta reload applicazione
|
|
/// </summary>
|
|
public event Action EA_ReloadRequested = null!;
|
|
|
|
/// <summary>
|
|
/// Evento calling a remote in corso
|
|
/// </summary>
|
|
public event Action EA_RemoteCalling = null!;
|
|
|
|
/// <summary>
|
|
/// Evento richiesta update applicazione (con check update app)
|
|
/// </summary>
|
|
public event Action EA_RestartRequested = null!;
|
|
|
|
/// <summary>
|
|
/// Evento update status controlli
|
|
/// </summary>
|
|
public event Action EA_StatusUpdated = null!;
|
|
|
|
#endregion Public Events
|
|
|
|
#region Public Properties
|
|
|
|
public string AppKey
|
|
{
|
|
get => CurrCheck.CurrPatrolCont.AppKey;
|
|
set
|
|
{
|
|
if (CurrCheck.CurrPatrolCont.AppKey != value)
|
|
{
|
|
// verifico ammissibilità
|
|
CurrCheck.CurrPatrolCont.AppKey = value;
|
|
ReportConfigUpd();
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// verifica autorizzazione al canale, ovvero
|
|
/// - deve avere tutte le chiavi/registri di comunicazione
|
|
/// - CodImpiego e AppKey devono essere validate
|
|
/// </summary>
|
|
public bool ChannelAuth
|
|
{
|
|
get
|
|
{
|
|
// in primis deve avere i dati di configurazione
|
|
bool answ = CurrCheck.CurrPatrolCont.HasCommData;
|
|
if (answ)
|
|
{
|
|
// verifica sia valida (scadenza a tempo da ultimo controllo) chiave auth in remoto (cod impiego + AuthKey ...)
|
|
// FixMe ToDo !!!
|
|
}
|
|
return answ;
|
|
}
|
|
}
|
|
|
|
public bool CloudCallActive
|
|
{
|
|
get => cloudCallActive;
|
|
set
|
|
{
|
|
if (cloudCallActive != value)
|
|
{
|
|
cloudCallActive = value;
|
|
ReportRemoteCall();
|
|
}
|
|
}
|
|
}
|
|
|
|
public string CodApp
|
|
{
|
|
get => CurrCheck.CurrPatrolCont.CodApp;
|
|
set
|
|
{
|
|
if (CurrCheck.CurrPatrolCont.CodApp != value)
|
|
{
|
|
// verifico ammissibilità
|
|
CurrCheck.CurrPatrolCont.CodApp = value;
|
|
ReportConfigUpd();
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Dir applicazione
|
|
/// </summary>
|
|
public string DataDir { get; set; } = "";
|
|
|
|
/// <summary>
|
|
/// ABilitazione glocale notifiche da conf
|
|
/// </summary>
|
|
public bool EnableNotify
|
|
{
|
|
get => CurrCheck.CurrPatrolCont.EnableNotify;
|
|
}
|
|
|
|
public List<VersStatusDTO> ListAppStatus
|
|
{
|
|
get => CurrCheck.ListAppStatus;
|
|
set
|
|
{
|
|
CurrCheck.ListAppStatus = value;
|
|
ReportStatusUpd();
|
|
}
|
|
}
|
|
|
|
public string MainKey
|
|
{
|
|
get => CurrCheck.CurrPatrolCont.MainKey;
|
|
set
|
|
{
|
|
if (CurrCheck.CurrPatrolCont.MainKey != value)
|
|
{
|
|
// verifico ammissibilità
|
|
CurrCheck.CurrPatrolCont.MainKey = value;
|
|
ReportConfigUpd();
|
|
}
|
|
}
|
|
}
|
|
|
|
public int RefreshPeriod
|
|
{
|
|
get => CurrCheck.CurrPatrolCont.RefreshIntSec;
|
|
set
|
|
{
|
|
if (CurrCheck.CurrPatrolCont.RefreshIntSec != value)
|
|
{
|
|
// verifico ammissibilità
|
|
CurrCheck.CurrPatrolCont.RefreshIntSec = value < refPMin ? refPMin : value > refPMax ? refPMax : value;
|
|
ReportConfigUpd();
|
|
}
|
|
}
|
|
}
|
|
|
|
public List<ControlTarget> TargetList
|
|
{
|
|
get => CurrCheck.CurrPatrolCont.TargetList;
|
|
set
|
|
{
|
|
CurrCheck.CurrPatrolCont.TargetList = value;
|
|
ReportConfigUpd();
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// num minuti veto controllo COMPLETO
|
|
/// </summary>
|
|
public int VetoCheck
|
|
{
|
|
get => CurrCheck.CurrPatrolCont.VetoCheckMinutes;
|
|
set
|
|
{
|
|
if (CurrCheck.CurrPatrolCont.VetoCheckMinutes != value)
|
|
{
|
|
// verifico ammissibilità
|
|
CurrCheck.CurrPatrolCont.VetoCheckMinutes = value < vetoPMin ? vetoPMin : value > vetoPMax ? vetoPMax : value;
|
|
ReportConfigUpd();
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// num minuti veto controllo refresh
|
|
/// </summary>
|
|
public int VetoRefresh
|
|
{
|
|
get => CurrCheck.CurrPatrolCont.VetoRefreshMinutes;
|
|
}
|
|
|
|
#endregion Public Properties
|
|
|
|
#region Public Methods
|
|
|
|
/// <summary>
|
|
/// Verifica se sia stato assegnato il codice licenza x una richiesta di enroll e nel caso recupera licenza e restituisce il codice da salvare in conf
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
public async Task<string> CheckAssignIdxLic()
|
|
{
|
|
string tVal = "";
|
|
// verifico dati richeista enroll, altrimenti faccio refresh richiesta...
|
|
if (CurrEnrollData.IdReq == 0)
|
|
{
|
|
int newCode = await GetAuthPassocde();
|
|
}
|
|
|
|
CloudCallActive = true;
|
|
// recupero info
|
|
EnrollRequestDTO updRec = await CurrCheck.CheckCurrEnroll();
|
|
if (updRec.IdReq > 0)
|
|
{
|
|
CurrEnrollData = updRec;
|
|
// se la licenza è valida --> procedo!
|
|
if (updRec.IdxLic > 0)
|
|
{
|
|
LicenzaDTO currLic = await CurrCheck.GetEnrollLic();
|
|
// se licenza valida --> restituisco e salvo!
|
|
if (currLic.IsValid && currLic.IsActive && !string.IsNullOrEmpty(currLic.Chiave))
|
|
{
|
|
tVal = currLic.Chiave;
|
|
CurrCheck.CurrPatrolCont.MainKey = currLic.Chiave;
|
|
// Ricalcolo valori subLic...
|
|
ResetSubLic(true);
|
|
await Task.Delay(10);
|
|
// verifico attivazioni
|
|
bool fatto = await CheckAttivazioni();
|
|
// ... e salvo
|
|
DoSaveConfig();
|
|
}
|
|
}
|
|
}
|
|
CloudCallActive = false;
|
|
return tVal;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Chiamata verifica attivazioni
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
public async Task<bool> CheckAttivazioni()
|
|
{
|
|
Stopwatch sw = new Stopwatch();
|
|
sw.Start();
|
|
bool fatto = await CurrCheck.CheckAttivazioni();
|
|
sw.Stop();
|
|
StatsCollector.UpdateStat($"CheckAttivazioni", sw.Elapsed);
|
|
return fatto;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Effettua un controllo completo (locale e remoto)
|
|
/// </summary>
|
|
/// <param name="doForce">se true esegue anche prima della scadenza veto</param>
|
|
public async Task DoFullCheckAsync(bool doForce)
|
|
{
|
|
DateTime adesso = DateTime.Now;
|
|
Stopwatch sw = new Stopwatch();
|
|
sw.Start();
|
|
if (lastCheckDone.AddMinutes(VetoRefresh) < adesso || doForce)
|
|
{
|
|
CloudCallActive = true;
|
|
lastCheckDone = adesso;
|
|
// se non è forzato controllo ultimo check
|
|
// in primis controllo se il remote è ok sennò mi fermo...
|
|
bool remoteOk = await CurrCheck.CheckRemote();
|
|
if (remoteOk)
|
|
{
|
|
await CurrCheck.SetManaged();
|
|
// effettua un refresh del controllo status...
|
|
bool locCheckOk = CurrCheck.UpdateLocalStatus(doForce);
|
|
bool remCheckOk = false;
|
|
bool critCheckOk = false;
|
|
if (locCheckOk)
|
|
{
|
|
remCheckOk = await CurrCheck.CheckRemoteReleases();
|
|
}
|
|
// infine effettua una verifica dello status "release critiche"
|
|
critCheckOk = await CurrCheck.CheckCriticalReport();
|
|
if (remCheckOk || critCheckOk)
|
|
{
|
|
ReportStatusUpd();
|
|
}
|
|
}
|
|
CloudCallActive = false;
|
|
// predispongo x check task successivo...
|
|
vetoTaskCheck = adesso.AddSeconds(-1);
|
|
|
|
// Collezione statistiche esecuzione
|
|
sw.Stop();
|
|
string checkType = doForce ? "Forced" : "Standard";
|
|
StatsCollector.UpdateStat($"AppCheck{checkType}", sw.Elapsed);
|
|
// invio statistiche esecuzione...
|
|
await DoSendRunStats();
|
|
}
|
|
}
|
|
|
|
/// <summary> Effettua rilettura configurazione e setup controlli... </summary
|
|
public void DoReloadConfig()
|
|
{
|
|
try
|
|
{
|
|
CurrCheck = new ReleaseChecker(ConfDir, DataDir);
|
|
Log.Trace($"Riletta config Setup | {ConfDir} | {DataDir}");
|
|
}
|
|
catch (Exception exc)
|
|
{
|
|
Log.Equals($"Eccezione in DoReloadConfig{Environment.NewLine}{exc}");
|
|
}
|
|
ReportConfigUpd();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Effettua salvataggio configurazione
|
|
/// </summary>
|
|
public void DoSaveConfig()
|
|
{
|
|
try
|
|
{
|
|
var rawData = JsonConvert.SerializeObject(CurrCheck.CurrPatrolCont, Formatting.Indented);
|
|
if (rawData != null && rawData.Length > 2)
|
|
{
|
|
File.WriteAllText(CurrCheck.ConfPath, rawData);
|
|
Log.Trace($"Effettuato salvataggio Config Setup! | {ConfDir} | {DataDir}");
|
|
}
|
|
}
|
|
catch (Exception exc)
|
|
{
|
|
Log.Equals($"Eccezione in DoSaveConfig{Environment.NewLine}{exc}");
|
|
}
|
|
ReportConfigUpd();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Effettua un controllo dei task da eseguire
|
|
/// </summary>
|
|
/// <param name="doForce">se true esegue anche prima della scadenza veto</param>
|
|
public async Task DoTaskCheckAsync(bool doForce)
|
|
{
|
|
Stopwatch sw = new Stopwatch();
|
|
DateTime adesso = DateTime.Now;
|
|
bool sendStats = false;
|
|
if (vetoTaskCheck < adesso || doForce || numFastCheck > 0)
|
|
{
|
|
// veto random prossimo controllo default 2 min (media)...
|
|
double vetoSec = (double)rnd.Next(10000, 14000) / 100;
|
|
if (numFastCheck > 0)
|
|
{
|
|
numFastCheck--;
|
|
}
|
|
// verifica se ci siano task da eseguire...
|
|
var task2exe = await CurrCheck.TaskGetReq(DeviceName);
|
|
if (task2exe != null && task2exe.Count > 0)
|
|
{
|
|
// in primis li segnala in running...
|
|
await CurrCheck.TaskSetRunning(DeviceName, task2exe);
|
|
// imposto limite a scalare x i prox fast check avendo trovato task da eseguire...
|
|
numFastCheck = RuntimeConfInt("CountNumFastCheck");
|
|
Dictionary<string, string> taskResults = new Dictionary<string, string>();
|
|
// eseguo 1:1 ...
|
|
foreach (var currTask in task2exe)
|
|
{
|
|
var cResp = await ExecuteTask(currTask);
|
|
// provo ad accodare risposte...
|
|
foreach (var resp in cResp)
|
|
{
|
|
if (taskResults.ContainsKey(resp.Key))
|
|
{
|
|
taskResults[resp.Key] = resp.Value;
|
|
}
|
|
else
|
|
{
|
|
taskResults.Add(resp.Key, resp.Value);
|
|
}
|
|
}
|
|
}
|
|
// invio risposta esito esecuzione finale
|
|
await CurrCheck.TaskSetDone(DeviceName, taskResults);
|
|
sendStats = true;
|
|
}
|
|
// imposto veto controlli task
|
|
vetoTaskCheck = adesso.AddSeconds(vetoSec);
|
|
|
|
// Collezione statistiche esecuzione
|
|
sw.Stop();
|
|
StatsCollector.UpdateStat($"TaskCheck", sw.Elapsed);
|
|
if (sendStats)
|
|
{
|
|
// invio statistiche esecuzione...
|
|
await DoSendRunStats();
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Restituisce un codice di auth temporaneo INT da impiegare x autorizzare
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
public async Task<int> GetAuthPassocde()
|
|
{
|
|
int tVal = 0;
|
|
//verifico che NON ci sia una richiesta già in corso...
|
|
if (CurrEnrollData.IdReq == 0)
|
|
{
|
|
Dictionary<string, string> reqInfo = DeviceInfoDict();
|
|
|
|
CloudCallActive = true;
|
|
// faccio la chiamata rest e salvo risposta...
|
|
CurrEnrollData = await CurrCheck.GetNewEnroll(reqInfo);
|
|
CloudCallActive = false;
|
|
}
|
|
|
|
// risposta valida se trovo un id richeista > 0...
|
|
if (CurrEnrollData.IdReq > 0)
|
|
{
|
|
tVal = CurrEnrollData.Passcode;
|
|
}
|
|
return tVal;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Metodo update specifico x app IobWin a step
|
|
/// </summary>
|
|
/// <param name="reqApp"></param>
|
|
/// <param name="step">Step richiesto: 1=backup conf, 2=download, 3=unzip, $=fix conf e close</param>
|
|
/// <returns></returns>
|
|
public async Task IobWinUpdateStep(VersStatusDTO reqApp, int step)
|
|
{
|
|
Stopwatch sw = new Stopwatch();
|
|
sw.Start();
|
|
// eseguo step secondo richiesta...
|
|
switch (step)
|
|
{
|
|
case 1:
|
|
await IobWinDoBackup(reqApp);
|
|
break;
|
|
|
|
case 2:
|
|
await IobWinDownload(reqApp);
|
|
break;
|
|
|
|
case 3:
|
|
await IobWinUnzip(reqApp);
|
|
break;
|
|
|
|
case 4:
|
|
await IobWinRestoreConf(reqApp);
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
sw.Stop();
|
|
StatsCollector.UpdateStat($"AppUpdate", sw.Elapsed);
|
|
}
|
|
|
|
public void ResetConf()
|
|
{
|
|
bool fatto = CurrCheck.ResetConf();
|
|
if (fatto)
|
|
{
|
|
ReportConfigUpd();
|
|
ReportStatusUpd();
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Reimposta CodImpiego / AppKey da librerie Egw secondo richiesta...
|
|
/// </summary>
|
|
/// <param name="resAppKey"></param>
|
|
public void ResetSubLic(bool resAppKey)
|
|
{
|
|
if (resAppKey)
|
|
{
|
|
CurrCheck.CurrPatrolCont.AppKey = SubLicManager.GenKey(CodApp);
|
|
}
|
|
ReportConfigUpd();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Invia info configurazione (directory)
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
public async Task SendConfTarget()
|
|
{
|
|
// preparo un task di conf da inviare
|
|
var task2send = new Dictionary<string, string>();
|
|
string rawConf = JsonConvert.SerializeObject(CurrCheck.CurrPatrolCont.TargetList);
|
|
task2send.Add("TargetList", rawConf);
|
|
await Task.Delay(500);
|
|
await CurrCheck.TaskSetDone(DeviceName, task2send);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Invia info licenza (se disponibili)
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
public async Task SendLicInfo()
|
|
{
|
|
if (CurrCheck.LicenceFilesDict.Count > 0)
|
|
{
|
|
// serializzo risultato
|
|
string rawData = JsonConvert.SerializeObject(CurrCheck.LicenceFilesDict);
|
|
Dictionary<string, string> licInfo = new Dictionary<string, string>();
|
|
// chiave: LicInfo
|
|
licInfo.Add("LicInfo", rawData);
|
|
// invio!
|
|
await CurrCheck.TaskSetDone(DeviceName, licInfo);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Invia info di reboot effettuato (spostando da req/run a done...)
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
public async Task SendRebooted()
|
|
{
|
|
// preparo un task di reboot da inviare
|
|
var task2send = new Dictionary<string, string>();
|
|
task2send.Add("ExecStart", $"{DateTime.Now:yyyy-MM-dd HH:mm:ss}");
|
|
await CurrCheck.TaskSetRunning(DeviceName, task2send);
|
|
await Task.Delay(500);
|
|
await CurrCheck.TaskSetDone(DeviceName, task2send);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Invia info satats preliminari
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
public async Task SendStats()
|
|
{
|
|
// invio statistiche esecuzione...
|
|
await DoSendRunStats();
|
|
}
|
|
|
|
#endregion Public Methods
|
|
|
|
#region Protected Fields
|
|
|
|
protected string DeviceName = "";
|
|
|
|
protected UpdateMan updateMan = new UpdateMan();
|
|
|
|
protected UpdateMan updateManAuth = new UpdateMan("SWDownloader", "viaD@nte16");
|
|
|
|
#endregion Protected Fields
|
|
|
|
#region Protected Properties
|
|
|
|
protected SubLicManager SubLicManager { get; set; } = new SubLicManager();
|
|
|
|
#endregion Protected Properties
|
|
|
|
#region Protected Methods
|
|
|
|
/// <summary>
|
|
/// Helper copia directory + contenuto
|
|
/// </summary>
|
|
/// <param name="sourceDir"></param>
|
|
/// <param name="destDir"></param>
|
|
protected void CopyDirectory(string sourceDir, string destDir)
|
|
{
|
|
// Create the destination directory if it doesn't exist
|
|
if (!Directory.Exists(destDir))
|
|
{
|
|
Directory.CreateDirectory(destDir);
|
|
}
|
|
|
|
// copio SOLO SE ho la dir di partenza
|
|
if (Directory.Exists(sourceDir))
|
|
{
|
|
// Copy all files
|
|
foreach (var file in Directory.GetFiles(sourceDir))
|
|
{
|
|
string destFile = Path.Combine(destDir, Path.GetFileName(file));
|
|
File.Copy(file, destFile, true);
|
|
}
|
|
|
|
// Copy all subdirectories
|
|
foreach (var dir in Directory.GetDirectories(sourceDir))
|
|
{
|
|
string destSubDir = Path.Combine(destDir, Path.GetFileName(dir));
|
|
CopyDirectory(dir, destSubDir);
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Esegue recupero dati licenze oxysec e li invia a LiMan
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
protected async Task DoSendLicInfo()
|
|
{
|
|
// chiamo metodo di update licenze...
|
|
var hasLic = CurrCheck.UpdateLicenceInfo();
|
|
if (hasLic)
|
|
{
|
|
// serializzo risultato
|
|
string rawData = JsonConvert.SerializeObject(CurrCheck.LicenceFilesDict);
|
|
Dictionary<string, string> licInfo = new Dictionary<string, string>();
|
|
// chiave: LicInfo
|
|
licInfo.Add("LicInfo", rawData);
|
|
// invio!
|
|
await CurrCheck.TaskSetDone(DeviceName, licInfo);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Esegue recupero dati statistiche esecuzione e li invia a LiMan
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
protected async Task DoSendRunStats()
|
|
{
|
|
// recupero statistiche
|
|
var statsData = StatsCollector.CurrentInfo();
|
|
string rawData = JsonConvert.SerializeObject(statsData);
|
|
Dictionary<string, string> statsInfo = new Dictionary<string, string>();
|
|
// chiave: RunStats
|
|
statsInfo.Add("RunStats", rawData);
|
|
// invio!
|
|
await CurrCheck.TaskSetDone(DeviceName, statsInfo);
|
|
}
|
|
|
|
#endregion Protected Methods
|
|
|
|
#region Private Fields
|
|
|
|
/// <summary>
|
|
/// Classe logger
|
|
/// </summary>
|
|
private static Logger Log = LogManager.GetCurrentClassLogger();
|
|
|
|
/// <summary>
|
|
/// Directory di backup x IobWin
|
|
/// </summary>
|
|
private string backupDir = @"C:\Steamware\backup";
|
|
|
|
/// <summary>
|
|
/// DataOra ultimo controllo effettuato
|
|
/// </summary>
|
|
private DateTime lastCheckDone = DateTime.Today.AddMonths(-1);
|
|
|
|
/// <summary>
|
|
/// Numero di controlli fast (5 sec medi) dei task prima di tornare alla gestione lenta (2 min)
|
|
/// </summary>
|
|
private int numFastCheck = 0;
|
|
|
|
/// <summary>
|
|
/// Valore massimo ammesso refresh sec
|
|
/// </summary>
|
|
private int refPMax = 3600;
|
|
|
|
/// <summary>
|
|
/// Valore minimo ammesso refresh sec
|
|
/// </summary>
|
|
private int refPMin = 1;
|
|
|
|
private Random rnd = new Random();
|
|
|
|
/// <summary>
|
|
/// Configurazione parametri speciali a runtime (con override da remoto...)
|
|
/// </summary>
|
|
private Dictionary<string, string> RuntimeConfDict = new Dictionary<string, string>();
|
|
|
|
/// <summary>
|
|
/// Directory temp di appoggio
|
|
/// </summary>
|
|
private string tempDir = @"C:\Steamware\temp";
|
|
|
|
/// <summary>
|
|
/// File segnaposto x lock fasi di update
|
|
/// </summary>
|
|
private string updFilePath = @"c:\Steamware\IOB-MAN\update.run";
|
|
|
|
/// <summary>
|
|
/// Valore massimo ammesso veto minuti
|
|
/// </summary>
|
|
private int vetoPMax = 14400;
|
|
|
|
/// <summary>
|
|
/// Valore minimo ammesso veto minuti
|
|
/// </summary>
|
|
private int vetoPMin = 30;
|
|
|
|
/// <summary>
|
|
/// DataOra ultimo controllo della parte TASK da eseguire
|
|
/// </summary>
|
|
private DateTime vetoTaskCheck = DateTime.Today;
|
|
|
|
/// <summary>
|
|
/// Ms di attesa x uscita processo (std)
|
|
/// </summary>
|
|
private int waitForExitMsec = 250;
|
|
|
|
#endregion Private Fields
|
|
|
|
#region Private Properties
|
|
|
|
private bool cloudCallActive { get; set; } = false;
|
|
|
|
private string CodImpiego { get; set; } = "";
|
|
|
|
private string ConfDir { get; set; } = "";
|
|
|
|
private ReleaseChecker CurrCheck { get; set; } = null!;
|
|
|
|
/// <summary>
|
|
/// Richiesta enroll corrente (se presente come file oppure nuova...)
|
|
/// </summary>
|
|
private EnrollRequestDTO CurrEnrollData
|
|
{
|
|
get => CurrCheck.CurrEnrollData;
|
|
set => CurrCheck.CurrEnrollData = value;
|
|
}
|
|
|
|
private SubLicManager SLicManager { get; set; } = new SubLicManager();
|
|
|
|
#endregion Private Properties
|
|
|
|
#region Private Methods
|
|
|
|
/// <summary>
|
|
/// Predispone un dizionario delle info del device + ID x inviare
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
private static Dictionary<string, string> DeviceInfoDict()
|
|
{
|
|
// in primis preparo dizionario dei dati da allegare alla richiesta
|
|
Dictionary<string, string> reqInfo = new Dictionary<string, string>();
|
|
// in primis setup dati dizionario conf...
|
|
if (DictUserInfo == null || DictUserInfo.Count == 0)
|
|
{
|
|
DictUserInfo = new Dictionary<string, string>(MachineDataValidator.userInfo);
|
|
}
|
|
if (DictNetInfo == null || DictNetInfo.Count == 0)
|
|
{
|
|
DictNetInfo = new Dictionary<string, string>(MachineDataValidator.netInfo);
|
|
}
|
|
if (DictMachineInfo == null || DictMachineInfo.Count == 0)
|
|
{
|
|
DictMachineInfo = new Dictionary<string, string>(DictUserInfo);
|
|
foreach (var item in DictNetInfo)
|
|
{
|
|
if (!DictMachineInfo.ContainsKey(item.Key))
|
|
{
|
|
DictMachineInfo.Add(item.Key, item.Value);
|
|
}
|
|
}
|
|
}
|
|
// Iniziallizzo con dati MachineInfo...
|
|
reqInfo = new Dictionary<string, string>(DictMachineInfo);
|
|
foreach (var item in new Dictionary<string, string>(MachineDataValidator.netInfo))
|
|
{
|
|
if (!reqInfo.ContainsKey(item.Key))
|
|
{
|
|
reqInfo.Add(item.Key, item.Value);
|
|
}
|
|
}
|
|
// ora i dati DeviceId da allegare in coda
|
|
string deviceId = new DeviceIdBuilder()
|
|
.AddMachineName()
|
|
.AddUserName()
|
|
.AddOsVersion()
|
|
.OnWindows(windows => windows
|
|
.AddMacAddressFromWmi(excludeWireless: true, excludeNonPhysical: true)
|
|
.AddProcessorId()
|
|
.AddMotherboardSerialNumber()
|
|
.AddSystemDriveSerialNumber())
|
|
.ToString();
|
|
// raggiungo DevideID
|
|
reqInfo.Add("DeviceID", deviceId);
|
|
return reqInfo;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Elimina contenuto directory
|
|
/// </summary>
|
|
/// <param name="directoryPath"></param>
|
|
private void DeleteDirectoryContents(string directoryPath)
|
|
{
|
|
// recupero info dir
|
|
DirectoryInfo directory = new DirectoryInfo(directoryPath);
|
|
// elimina file
|
|
foreach (FileInfo file in directory.GetFiles())
|
|
{
|
|
file.Delete();
|
|
}
|
|
// elimina ulteriori directory
|
|
foreach (DirectoryInfo subDirectory in directory.GetDirectories())
|
|
{
|
|
subDirectory.Delete(true);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Esecuzione vero e proprio task richiesto
|
|
/// </summary>
|
|
/// <param name="item"></param>
|
|
/// <returns></returns>
|
|
private async Task<Dictionary<string, string>> ExecuteTask(KeyValuePair<string, string> item)
|
|
{
|
|
Dictionary<string, string> taskDone = new Dictionary<string, string>();
|
|
bool taskOk = false;
|
|
string taskVal = "";
|
|
Stopwatch sw = Stopwatch.StartNew();
|
|
// converto richiesta in enum...
|
|
CoreEnum.EgwAccTask tName = CoreEnum.EgwAccTask.ND;
|
|
Enum.TryParse(item.Key, out tName);
|
|
// switch sui vari casi x eseguire...
|
|
switch (tName)
|
|
{
|
|
//case CoreEnum.EgwAccTask.AppSearch:
|
|
// break;
|
|
|
|
case CoreEnum.EgwAccTask.DeviceInfoGet:
|
|
Dictionary<string, string> currDevInfo = DeviceInfoDict();
|
|
taskVal = JsonConvert.SerializeObject(currDevInfo, Formatting.Indented);
|
|
break;
|
|
|
|
case CoreEnum.EgwAccTask.ForceCheck:
|
|
Dictionary<string, string> fcDetail = new Dictionary<string, string>();
|
|
fcDetail.Add("ExecStart", $"{DateTime.Now:yyyy-MM-dd HH:mm:ss}");
|
|
await DoFullCheckAsync(true);
|
|
sw.Stop();
|
|
fcDetail.Add("Completed", $"App Check done in {sw.Elapsed.TotalMilliseconds:N0}ms");
|
|
taskVal = JsonConvert.SerializeObject(fcDetail, Formatting.Indented);
|
|
break;
|
|
|
|
case CoreEnum.EgwAccTask.ForceReload:
|
|
Dictionary<string, string> fcReload = new Dictionary<string, string>();
|
|
fcReload.Add("ExecReload", $"{DateTime.Now:yyyy-MM-dd HH:mm:ss}");
|
|
sw.Stop();
|
|
// mando subito conferma esecuzione...
|
|
fcReload.Add("ExecReload", $"Reload Requested...");
|
|
taskVal = JsonConvert.SerializeObject(fcReload, Formatting.Indented);
|
|
// sollevo evento
|
|
if (EA_ReloadRequested != null)
|
|
{
|
|
EA_ReloadRequested?.Invoke();
|
|
}
|
|
break;
|
|
|
|
case CoreEnum.EgwAccTask.ForceUpdate:
|
|
Dictionary<string, string> fcUpdate = new Dictionary<string, string>();
|
|
fcUpdate.Add("ExecStart", $"{DateTime.Now:yyyy-MM-dd HH:mm:ss}");
|
|
sw.Stop();
|
|
// mando subito conferma esecuzione...
|
|
taskVal = JsonConvert.SerializeObject(fcUpdate, Formatting.Indented);
|
|
// sollevo evento
|
|
if (EA_RestartRequested != null)
|
|
{
|
|
EA_RestartRequested?.Invoke();
|
|
}
|
|
break;
|
|
|
|
case CoreEnum.EgwAccTask.OxyLicenseGet:
|
|
await DoSendLicInfo();
|
|
break;
|
|
|
|
//case CoreEnum.EgwAccTask.ParamDictReset:
|
|
// break;
|
|
|
|
//case CoreEnum.EgwAccTask.ParamUpsert:
|
|
// break;
|
|
|
|
case CoreEnum.EgwAccTask.TargetListUpsert:
|
|
// verifico se nel payload c'è la configurazione VALIDA...
|
|
if (string.IsNullOrEmpty(item.Value))
|
|
{
|
|
taskVal = "Error: empty Payload";
|
|
}
|
|
else
|
|
{
|
|
// provo a deserializzare oggetto
|
|
var newTargetList = JsonConvert.DeserializeObject<List<ControlTarget>>(item.Value);
|
|
if (newTargetList == null || newTargetList.Count == 0)
|
|
{
|
|
taskVal = "Error: empty List";
|
|
}
|
|
else
|
|
{
|
|
// se valido sovrascrivo e salvo!
|
|
CurrCheck.CurrPatrolCont.TargetList = newTargetList;
|
|
CurrCheck.SaveConfig();
|
|
}
|
|
}
|
|
break;
|
|
|
|
case CoreEnum.EgwAccTask.ND:
|
|
default:
|
|
taskVal = $"taskReq: {tName} | key: {item.Key} | val: {item.Value} | SKIPPED | NO EXEC";
|
|
Log.Info($"Chiamata senza processing: taskOk: {taskOk} | taskVal: {taskVal}");
|
|
break;
|
|
}
|
|
// aggiungo task!
|
|
taskDone.Add(item.Key, taskVal);
|
|
// aggiungo task ultima esecuzione...
|
|
Dictionary<string, string> finDet = new Dictionary<string, string>();
|
|
finDet.Add("Completed", $"{DateTime.Now:yyyy-MM-dd HH:mm:ss}");
|
|
taskVal = JsonConvert.SerializeObject(finDet, Formatting.Indented);
|
|
taskDone.Add("LastTaskExec", taskVal);
|
|
StatsCollector.UpdateStat($"Exec{item.Key}", sw.Elapsed);
|
|
return taskDone;
|
|
}
|
|
|
|
/// <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)
|
|
{
|
|
Log.Error($"Process not Killed, 2nd try p.kill()");
|
|
p.Kill();
|
|
p.WaitForExit(waitForExitMsec * 2);
|
|
}
|
|
if (!p.HasExited)
|
|
{
|
|
Log.Error($"Process not Killed, 3th try p.kill()");
|
|
p.Kill();
|
|
}
|
|
}
|
|
}
|
|
catch (Exception exc)
|
|
{
|
|
Log.Error($"Errore in fase di kill processo da nome {exc}");
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Step preliminare di backup conf e app corrente
|
|
/// </summary>
|
|
/// <param name="reqApp"></param>
|
|
/// <returns></returns>
|
|
private async Task IobWinDoBackup(VersStatusDTO reqApp)
|
|
{
|
|
// controllo di avere un file di riferimento...
|
|
string appDir = Path.GetDirectoryName(reqApp.LocalPath) ?? "";
|
|
if (!string.IsNullOrEmpty(appDir))
|
|
{
|
|
string tempZip = Path.Combine(tempDir, "FULL", reqApp.CodApp);
|
|
// step 0: inserisce i file semaforo di segnalazione update in corso
|
|
using (FileStream fs = File.Create(updFilePath))
|
|
{
|
|
// File is created and access is released when the using block ends
|
|
}
|
|
|
|
// step 1: backup configurazioni partendo da path applicazione...
|
|
string srcDir = Path.Combine(appDir, "DATA", "CONF");
|
|
string destDir = Path.Combine(backupDir, "Conf", reqApp.CodApp, "DATA", "CONF");
|
|
// se MAN uso folder "accorciata"
|
|
if (reqApp.CodApp == "IOB-MAN")
|
|
{
|
|
srcDir = Path.Combine(appDir, "CONF");
|
|
destDir = Path.Combine(backupDir, "Conf", reqApp.CodApp, "CONF");
|
|
}
|
|
CopyDirectory(srcDir, destDir);
|
|
|
|
// step 2: kill processi
|
|
ForceKillByName(reqApp.CodApp);
|
|
|
|
// step 3: backup + zip intera folder applicativo
|
|
if (Directory.Exists(tempZip))
|
|
{
|
|
Directory.Delete(tempZip, true);
|
|
}
|
|
Directory.CreateDirectory(tempZip);
|
|
CopyDirectory(appDir, tempZip);
|
|
|
|
string zipPath = Path.Combine(backupDir, "Archive", reqApp.CodApp, $"{DateTime.Now:yyyyMMdd}_{DateTime.Now:HHmmss}.zip");
|
|
if (File.Exists(zipPath))
|
|
{
|
|
File.Delete(zipPath);
|
|
}
|
|
else
|
|
{
|
|
string zipDir = Path.GetDirectoryName(zipPath) ?? "";
|
|
if (!string.IsNullOrEmpty(zipDir))
|
|
{
|
|
if (!Directory.Exists(zipDir))
|
|
{
|
|
Directory.CreateDirectory(zipDir);
|
|
}
|
|
}
|
|
}
|
|
await Task.Run(() =>
|
|
{
|
|
ZipFile.CreateFromDirectory(tempZip, zipPath);
|
|
});
|
|
}
|
|
await Task.Delay(10);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Step di download da remoto
|
|
/// </summary>
|
|
/// <param name="reqApp"></param>
|
|
/// <returns></returns>
|
|
private async Task IobWinDownload(VersStatusDTO reqApp)
|
|
{
|
|
// step 4: download // controllo di avere un file di riferimento...
|
|
string appDir = Path.GetDirectoryName(reqApp.LocalPath) ?? "";
|
|
if (!string.IsNullOrEmpty(appDir))
|
|
{
|
|
string installerDir = Path.Combine(backupDir, "installer", reqApp.CodApp);
|
|
// se il path fosse vuoto --> uso quello standard da nexus...
|
|
string urlDownload = reqApp.UrlDownload;
|
|
if (string.IsNullOrEmpty(urlDownload))
|
|
{
|
|
urlDownload = $"https://nexus.steamware.net/repository/utility/MAPO/{reqApp.CodApp}/stable/{reqApp.CodApp}.zip";
|
|
}
|
|
long size = updateMan.DownloadApp(urlDownload, installerDir, reqApp.CodApp, reqApp.VersNumLast);
|
|
// se non andata provo con auth...
|
|
if (size == 0)
|
|
{
|
|
size = updateManAuth.DownloadApp(urlDownload, installerDir, reqApp.CodApp, reqApp.VersNumLast);
|
|
}
|
|
}
|
|
await Task.Delay(10);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Step di fix backup configurazioni + unlock file update run
|
|
/// </summary>
|
|
/// <param name="reqApp"></param>
|
|
/// <returns></returns>
|
|
private async Task IobWinRestoreConf(VersStatusDTO reqApp)
|
|
{
|
|
// step 6: restore conf
|
|
string appDir = Path.GetDirectoryName(reqApp.LocalPath) ?? "";
|
|
if (!string.IsNullOrEmpty(appDir))
|
|
{
|
|
string srcDir = Path.Combine(appDir, "DATA", "CONF");
|
|
string destDir = Path.Combine(backupDir, "Conf", reqApp.CodApp, "DATA", "CONF");
|
|
// se MAN uso folder "accorciata"
|
|
if (reqApp.CodApp == "IOB-MAN")
|
|
{
|
|
srcDir = Path.Combine(appDir, "CONF");
|
|
destDir = Path.Combine(backupDir, "Conf", reqApp.CodApp, "CONF");
|
|
}
|
|
|
|
CopyDirectory(destDir, srcDir);
|
|
}
|
|
// step 7: rimozione file lock semaforo
|
|
File.Delete(updFilePath);
|
|
await Task.Delay(10);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Step di unzip file scaricato
|
|
/// </summary>
|
|
/// <param name="reqApp"></param>
|
|
/// <returns></returns>
|
|
private async Task IobWinUnzip(VersStatusDTO reqApp)
|
|
{
|
|
// step 5: unzip + overwrite
|
|
string appDir = Path.GetDirectoryName(reqApp.LocalPath) ?? "";
|
|
if (!string.IsNullOrEmpty(appDir))
|
|
{
|
|
string installerDir = Path.Combine(backupDir, "installer", reqApp.CodApp);
|
|
string srcZip = Path.Combine(installerDir, $"{reqApp.CodApp}.zip");
|
|
// svuoto la dir di destinazione preliminarmente...
|
|
DeleteDirectoryContents(appDir);
|
|
// esegue unzip
|
|
ZipFile.ExtractToDirectory(srcZip, appDir, true);
|
|
}
|
|
await Task.Delay(10);
|
|
}
|
|
|
|
private void ReportConfigUpd()
|
|
{
|
|
if (EA_ConfigUpdated != null)
|
|
{
|
|
EA_ConfigUpdated?.Invoke();
|
|
}
|
|
}
|
|
|
|
private void ReportRemoteCall()
|
|
{
|
|
if (EA_RemoteCalling != null)
|
|
{
|
|
EA_RemoteCalling?.Invoke();
|
|
}
|
|
}
|
|
|
|
private void ReportStatusUpd()
|
|
{
|
|
if (EA_StatusUpdated != null)
|
|
{
|
|
// controllo se almeno 1 app abbia update...
|
|
foreach (var item in ListAppStatus)
|
|
{
|
|
if (item.HasUpdate)
|
|
{
|
|
EA_StatusUpdated?.Invoke();
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Recupera parametro conf in Runtime di tipo Int
|
|
/// </summary>
|
|
/// <param name="param"></param>
|
|
/// <returns></returns>
|
|
private int RuntimeConfInt(string param)
|
|
{
|
|
int answ = 0;
|
|
if (RuntimeConfDict.ContainsKey(param))
|
|
{
|
|
string retVal = RuntimeConfDict[param];
|
|
int.TryParse(retVal, out answ);
|
|
}
|
|
return answ;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Recupera parametro conf in Runtime di tipo Int
|
|
/// </summary>
|
|
/// <param name="param"></param>
|
|
/// <returns></returns>
|
|
private string RuntimeConfString(string param)
|
|
{
|
|
string answ = "";
|
|
if (RuntimeConfDict.ContainsKey(param))
|
|
{
|
|
answ = RuntimeConfDict[param];
|
|
}
|
|
return answ;
|
|
}
|
|
|
|
#endregion Private Methods
|
|
}
|
|
} |