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
///
/// Dizionario completo info macchina
///
public static Dictionary DictMachineInfo = new Dictionary();
///
/// Dizionario completo info networking
///
public static Dictionary DictNetInfo = new Dictionary();
///
/// Dizionario completo info utente
///
public static Dictionary DictUserInfo = new Dictionary();
#endregion Public Fields
#region Public Constructors
public AppControlService()
{
try
{
mainAssembly = Assembly.GetCallingAssembly();
string startDir = Path.GetDirectoryName(mainAssembly.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
///
/// Evento update configurazione
///
public event Action EA_ConfigUpdated = null!;
///
/// Evento richiesta reload applicazione
///
public event Action EA_ReloadRequested = null!;
///
/// Evento calling a remote in corso
///
public event Action EA_RemoteCalling = null!;
///
/// Evento richiesta update applicazione (con check update app)
///
public event Action EA_RestartRequested = null!;
///
/// Evento update status controlli
///
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();
}
}
}
///
/// verifica autorizzazione al canale, ovvero
/// - deve avere tutte le chiavi/registri di comunicazione
/// - CodImpiego e AppKey devono essere validate
///
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();
}
}
}
///
/// Dir applicazione
///
public string DataDir { get; set; } = "";
///
/// ABilitazione glocale notifiche da conf
///
public bool EnableNotify
{
get => CurrCheck.CurrPatrolCont.EnableNotify;
}
public List 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 TargetList
{
get => CurrCheck.CurrPatrolCont.TargetList;
set
{
CurrCheck.CurrPatrolCont.TargetList = value;
ReportConfigUpd();
}
}
///
/// num minuti veto controllo COMPLETO
///
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();
}
}
}
///
/// num minuti veto controllo refresh
///
public int VetoRefresh
{
get => CurrCheck.CurrPatrolCont.VetoRefreshMinutes;
}
#endregion Public Properties
#region Public Methods
///
/// 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
///
///
public async Task 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;
}
///
/// Chiamata verifica attivazioni
///
///
public async Task CheckAttivazioni()
{
Stopwatch sw = new Stopwatch();
sw.Start();
bool fatto = await CurrCheck.CheckAttivazioni();
sw.Stop();
StatsCollector.UpdateStat($"CheckAttivazioni", sw.Elapsed);
return fatto;
}
///
/// Effettua un controllo completo (locale e remoto)
///
/// se true esegue anche prima della scadenza veto
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();
}
}
/// Effettua rilettura configurazione e setup controlli...
/// Effettua salvataggio configurazione
///
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();
}
///
/// Effettua un controllo dei task da eseguire
///
/// se true esegue anche prima della scadenza veto
public async Task DoTaskCheckAsync(bool doForce)
{
Stopwatch sw = new Stopwatch();
sw.Start();
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)
{
CloudCallActive = true;
// in primis li segnala in running...
await CurrCheck.TaskSetRunningAsync(DeviceName, task2exe);
// imposto limite a scalare x i prox fast check avendo trovato task da eseguire...
numFastCheck = RuntimeConfInt("CountNumFastCheck");
Dictionary taskResults = new Dictionary();
// 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.TaskSetDoneAsync(DeviceName, taskResults);
sendStats = true;
CloudCallActive = false;
}
// 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();
}
}
}
///
/// Restituisce un codice di auth temporaneo INT da impiegare x autorizzare
///
///
public async Task GetAuthPassocde()
{
int tVal = 0;
//verifico che NON ci sia una richiesta già in corso...
if (CurrEnrollData.IdReq == 0)
{
Dictionary 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;
}
///
/// Metodo update specifico x app IobWin a step
///
///
/// Step richiesto: 1=backup conf, 2=download, 3=unzip, $=fix conf e close
///
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 ReportStatusUpd()
{
if (EA_StatusUpdated != null)
{
#if false
// controllo se almeno 1 app abbia update...
foreach (var item in ListAppStatus)
{
if (item.HasUpdate)
{
EA_StatusUpdated?.Invoke();
break;
}
}
#endif
EA_StatusUpdated?.Invoke();
}
}
public void ResetConf()
{
bool fatto = CurrCheck.ResetConf();
if (fatto)
{
ReportConfigUpd();
ReportStatusUpd();
}
}
///
/// Reimposta CodImpiego / AppKey da librerie Egw secondo richiesta...
///
///
public void ResetSubLic(bool resAppKey)
{
if (resAppKey)
{
CurrCheck.CurrPatrolCont.AppKey = SubLicManager.GenKey(CodApp);
}
ReportConfigUpd();
}
///
/// Invia info configurazione (directory)
///
///
public async Task SendConfTarget()
{
// preparo un task di conf da inviare
var task2send = new Dictionary();
string rawConf = JsonConvert.SerializeObject(CurrCheck.CurrPatrolCont.TargetList);
task2send.Add("TargetList", rawConf);
await CurrCheck.TaskSetDoneAsync(DeviceName, task2send);
}
///
/// Invia info licenza (se disponibili)
///
///
public async Task SendLicInfo()
{
if (CurrCheck.LicenceFilesDict.Count > 0)
{
// serializzo risultato
string rawData = JsonConvert.SerializeObject(CurrCheck.LicenceFilesDict);
Dictionary licInfo = new Dictionary();
// chiave: LicInfo
licInfo.Add("LicInfo", rawData);
// invio!
await CurrCheck.TaskSetDoneAsync(DeviceName, licInfo);
}
}
///
/// Invia immediatamente info di reboot effettuato (spostando da req/run a done...)
///
///
public void SendRebooted(bool sendReboot)
{
// preparo un task di reboot da inviare
var task2send = new Dictionary();
task2send.Add("ExecStart", $"{DateTime.Now:yyyy-MM-dd HH:mm:ss}");
CurrCheck.TaskSetRunning(DeviceName, task2send);
if (sendReboot)
{
// aggiungo anche rebooted...
task2send.Add("RebootRequest", $"{DateTime.Now:yyyy-MM-dd HH:mm:ss}");
}
CurrCheck.TaskSetDone(DeviceName, task2send);
}
///
/// Invia info di reboot effettuato (spostando da req/run a done...)
///
///
public async Task SendRebootedAsync(bool sendReboot)
{
// preparo un task di reboot da inviare
var task2send = new Dictionary();
task2send.Add("ExecStart", $"{DateTime.Now:yyyy-MM-dd HH:mm:ss}");
await CurrCheck.TaskSetRunningAsync(DeviceName, task2send);
await Task.Delay(50);
if (sendReboot)
{
// aggiungo anche rebooted...
task2send.Add("RebootRequest", $"{DateTime.Now:yyyy-MM-dd HH:mm:ss}");
}
await CurrCheck.TaskSetDoneAsync(DeviceName, task2send);
}
///
/// Invia info satats preliminari
///
///
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
///
/// Helper copia directory + contenuto
///
///
///
protected void CopyDirectory(string sourceDir, string destDir)
{
// Create the destination directory if it doesn't exist
if (!Directory.Exists(destDir))
{
Directory.CreateDirectory(destDir);
}
// copio SOLO SE ho la dir di partenza
if (Directory.Exists(sourceDir))
{
// Copy all files
foreach (var file in Directory.GetFiles(sourceDir))
{
string destFile = Path.Combine(destDir, Path.GetFileName(file));
File.Copy(file, destFile, true);
}
// Copy all subdirectories
foreach (var dir in Directory.GetDirectories(sourceDir))
{
string destSubDir = Path.Combine(destDir, Path.GetFileName(dir));
CopyDirectory(dir, destSubDir);
}
}
}
///
/// Esegue recupero dati licenze oxysec e li invia a LiMan
///
///
protected async Task DoSendLicInfo()
{
// chiamo metodo di update licenze...
var hasLic = CurrCheck.UpdateLicenceInfo();
if (hasLic)
{
// serializzo risultato
string rawData = JsonConvert.SerializeObject(CurrCheck.LicenceFilesDict);
Dictionary licInfo = new Dictionary();
// chiave: LicInfo
licInfo.Add("LicInfo", rawData);
// invio!
await CurrCheck.TaskSetDoneAsync(DeviceName, licInfo);
}
}
///
/// Esegue recupero dati statistiche esecuzione e li invia a LiMan
///
///
protected async Task DoSendRunStats()
{
// recupero statistiche
Dictionary statsData = StatsCollector.CurrentInfo();
// aggiungo versione alle statistiche
statsData.Add("Version", $"{mainAssembly.GetName().Version}");
//serializzo
string rawData = JsonConvert.SerializeObject(statsData);
Dictionary statsInfo = new Dictionary();
// chiave: RunStats
statsInfo.Add("RunStats", rawData);
// invio!
await CurrCheck.TaskSetDoneAsync(DeviceName, statsInfo);
}
#endregion Protected Methods
#region Private Fields
///
/// Classe logger
///
private static Logger Log = LogManager.GetCurrentClassLogger();
///
/// Directory di backup x IobWin
///
private string backupDir = @"C:\Steamware\backup";
///
/// DataOra ultimo controllo effettuato
///
private DateTime lastCheckDone = DateTime.Today.AddMonths(-1);
private Assembly mainAssembly = Assembly.GetExecutingAssembly();
///
/// Numero di controlli fast (5 sec medi) dei task prima di tornare alla gestione lenta (2 min)
///
private int numFastCheck = 0;
///
/// Valore massimo ammesso refresh sec
///
private int refPMax = 3600;
///
/// Valore minimo ammesso refresh sec
///
private int refPMin = 1;
private Random rnd = new Random();
///
/// Configurazione parametri speciali a runtime (con override da remoto...)
///
private Dictionary RuntimeConfDict = new Dictionary();
///
/// Directory temp di appoggio
///
private string tempDir = @"C:\Steamware\temp";
///
/// File segnaposto x lock fasi di update
///
private string updFilePath = @"c:\Steamware\IOB-MAN\update.run";
///
/// Valore massimo ammesso veto minuti
///
private int vetoPMax = 14400;
///
/// Valore minimo ammesso veto minuti
///
private int vetoPMin = 30;
///
/// DataOra ultimo controllo della parte TASK da eseguire
///
private DateTime vetoTaskCheck = DateTime.Today;
///
/// Ms di attesa x uscita processo (std)
///
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!;
///
/// Richiesta enroll corrente (se presente come file oppure nuova...)
///
private EnrollRequestDTO CurrEnrollData
{
get => CurrCheck.CurrEnrollData;
set => CurrCheck.CurrEnrollData = value;
}
private SubLicManager SLicManager { get; set; } = new SubLicManager();
#endregion Private Properties
#region Private Methods
///
/// Predispone un dizionario delle info del device + ID x inviare
///
///
private static Dictionary DeviceInfoDict()
{
// in primis preparo dizionario dei dati da allegare alla richiesta
Dictionary reqInfo = new Dictionary();
// in primis setup dati dizionario conf...
if (DictUserInfo == null || DictUserInfo.Count == 0)
{
DictUserInfo = new Dictionary(MachineDataValidator.userInfo);
}
if (DictNetInfo == null || DictNetInfo.Count == 0)
{
DictNetInfo = new Dictionary(MachineDataValidator.netInfo);
}
if (DictMachineInfo == null || DictMachineInfo.Count == 0)
{
DictMachineInfo = new Dictionary(DictUserInfo);
foreach (var item in DictNetInfo)
{
if (!DictMachineInfo.ContainsKey(item.Key))
{
DictMachineInfo.Add(item.Key, item.Value);
}
}
}
// Iniziallizzo con dati MachineInfo...
reqInfo = new Dictionary(DictMachineInfo);
foreach (var item in new Dictionary(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;
}
///
/// Elimina contenuto directory
///
///
private void DeleteDirectoryContents(string directoryPath)
{
// recupero info dir
DirectoryInfo directory = new DirectoryInfo(directoryPath);
// elimina file
foreach (FileInfo file in directory.GetFiles())
{
file.Delete();
}
// elimina ulteriori directory
foreach (DirectoryInfo subDirectory in directory.GetDirectories())
{
subDirectory.Delete(true);
}
}
///
/// Esecuzione vero e proprio task richiesto
///
///
///
private async Task> ExecuteTask(KeyValuePair item)
{
Dictionary taskDone = new Dictionary();
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.BackupSendConf:
Dictionary bsRes = new Dictionary();
bsRes.Add("ExecStart", $"{DateTime.Now:yyyy-MM-dd HH:mm:ss}");
await IobConfZipUpload();
sw.Stop();
taskVal = JsonConvert.SerializeObject(bsRes);
break;
case CoreEnum.EgwAccTask.DeviceInfoGet:
Dictionary currDevInfo = DeviceInfoDict();
taskVal = JsonConvert.SerializeObject(currDevInfo);
break;
case CoreEnum.EgwAccTask.ForceCheck:
Dictionary fcRes = new Dictionary();
fcRes.Add("ExecStart", $"{DateTime.Now:yyyy-MM-dd HH:mm:ss}");
await DoFullCheckAsync(true);
sw.Stop();
fcRes.Add("Completed", $"App Check done in {sw.Elapsed.TotalMilliseconds:N0}ms");
taskVal = JsonConvert.SerializeObject(fcRes);
break;
case CoreEnum.EgwAccTask.ForceReload:
Dictionary frRes = new Dictionary();
frRes.Add("ExecReload", $"{DateTime.Now:yyyy-MM-dd HH:mm:ss}");
sw.Stop();
taskVal = JsonConvert.SerializeObject(frRes);
// sollevo evento
if (EA_ReloadRequested != null)
{
EA_ReloadRequested?.Invoke();
}
break;
case CoreEnum.EgwAccTask.ForceUpdate:
Dictionary fuRes = new Dictionary();
fuRes.Add("ExecStart", $"{DateTime.Now:yyyy-MM-dd HH:mm:ss}");
sw.Stop();
// mando subito conferma esecuzione...
taskVal = JsonConvert.SerializeObject(fuRes);
RaiseRestartReq();
break;
case CoreEnum.EgwAccTask.OxyLicenseGet:
Dictionary olgRes = new Dictionary();
await DoSendLicInfo();
sw.Stop();
// mando subito conferma esecuzione...
olgRes.Add("LicInfoCompleted", $"{DateTime.Now:yyyy-MM-dd HH:mm:ss}");
taskVal = JsonConvert.SerializeObject(olgRes);
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>(item.Value);
if (newTargetList == null || newTargetList.Count == 0)
{
taskVal = "Error: empty List";
}
else
{
// se valido sovrascrivo e salvo!
CurrCheck.CurrPatrolCont.TargetList = newTargetList;
CurrCheck.SaveConfig();
// ... invio versione aggiornata
await Task.Delay(100);
await SendConfTarget();
}
}
break;
case CoreEnum.EgwAccTask.TargetAppUpdate:
// verifico se nel payload c'è valore dell'applciazione da aggiornare...
if (string.IsNullOrEmpty(item.Value))
{
taskVal = "Error: missing CodApp";
}
else
{
CloudCallActive = true;
// in primis chiamo aggiornamento stati release
await DoFullCheckAsync(true);
// il valore è il nome dell'app da aggiornare...
string codAppReq = item.Value;
// verifico da conf che la richiesta sia sensata (update x un app consentita...)
var ReqApp = ListAppStatus.FirstOrDefault(x => x.CodApp == codAppReq);
// se ho trovato...
if (ReqApp != null)
{
//verifica ulteriore tipo app e con update... limitato a WinApp...
if (ReqApp != null && ReqApp.ApplicationType == CoreEnum.AppType.WinApp && ReqApp.HasUpdate)
{ // esegue update delle app Iob-*
// "Backup Config"
await IobWinUpdateStep(ReqApp, 1);
// "Download update";
await IobWinUpdateStep(ReqApp, 2);
// "Unzip software";
await IobWinUpdateStep(ReqApp, 3);
// "Config Restore";
await IobWinUpdateStep(ReqApp, 4);
// update finale
await DoFullCheckAsync(true);
}
else
{
taskVal = $"Update non permesso per {codAppReq}";
}
}
else
{
taskVal = $"App non trovatao: {codAppReq}";
}
CloudCallActive = false;
ReportStatusUpd();
}
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 finDet = new Dictionary();
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;
}
///
/// Solleva evento richiesta restart
///
public void RaiseRestartReq()
{
// sollevo evento
if (EA_RestartRequested != null)
{
EA_RestartRequested?.Invoke();
}
}
///
/// Effettua un force kill dato nome processo
///
///
private void ForceKillByName(string nomeProc)
{
Process[] stillRunningProc = Process.GetProcessesByName(nomeProc);
if (stillRunningProc != null)
{
if (stillRunningProc.Length > 0)
{
foreach (var item in stillRunningProc)
{
try
{
Process p = Process.GetProcessById(item.Id);
{
if (!p.HasExited)
{
int closeWaitTime = waitForExitMsec * 8;
// se è MAN --> aspetto + a lungo...
if (nomeProc.Contains("IOB-MAN"))
{
closeWaitTime = closeWaitTime * 4;
}
p.CloseMainWindow();
p.WaitForExit(closeWaitTime);
}
if (!p.HasExited)
{
Log.Error($"Process not Exited, 2nd try p.kill()");
p.Kill();
p.WaitForExit(waitForExitMsec);
}
if (!p.HasExited)
{
Log.Error($"Process not Killed, 3nd try p.kill()");
p.Kill();
p.WaitForExit(waitForExitMsec * 2);
}
if (!p.HasExited)
{
Log.Error($"Process not Killed, 4th try p.kill()");
p.Kill();
}
}
}
catch (Exception exc)
{
Log.Error($"Errore in fase di kill processo da nome {exc}");
}
}
}
}
}
///
/// Effettua zip della folder di backup conf e la invia a LiMan
///
///
private async Task IobConfZipUpload()
{
// controllo che ci sia la firectory di partenza...
string confDir = Path.Combine(backupDir, "Conf");
if (Directory.Exists(confDir))
{
// preparo dir temporanea x zip
string tempZip = Path.Combine(tempDir, "ConfCopy");
if (Directory.Exists(tempZip))
{
Directory.Delete(tempZip, true);
}
Directory.CreateDirectory(tempZip);
// copio contenuto dir conf
CopyDirectory(confDir, tempZip);
// preparo zip
string zipPath = Path.Combine(tempDir, "IOB_Conf.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, CompressionLevel.Optimal, false);
});
// chiamo metodo x upload zip
bool uploaded = await CurrCheck.UploadZipfile(AppKey, zipPath);
// elimino dir di appoggio
if (Directory.Exists(tempZip))
{
Directory.Delete(tempZip, true);
}
}
await Task.Delay(10);
}
///
/// Step preliminare di backup conf e app corrente
///
///
///
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
string manDir = Path.GetDirectoryName(updFilePath) ?? "";
if (!string.IsNullOrEmpty(manDir))
{
if (!Directory.Exists(manDir))
{
Directory.CreateDirectory(manDir);
}
}
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");
// verifico se esista la srcDir, altrimenti uso solo CONF...
if (!Directory.Exists(srcDir))
{
srcDir = Path.Combine(appDir, "CONF");
destDir = Path.Combine(backupDir, "Conf", reqApp.CodApp, "CONF");
}
CopyDirectory(srcDir, destDir);
// step 2a: kill log...
ForceKillByName("TailBlazer");
ForceKillByName("Tail Blazer");
// step 2b: 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);
}
///
/// Step di download da remoto
///
///
///
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);
}
///
/// Step di fix backup configurazioni + unlock file update run
///
///
///
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");
if (!Directory.Exists(destDir))
{
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);
}
///
/// Step di unzip file scaricato
///
///
///
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();
}
}
///
/// Recupera parametro conf in Runtime di tipo Int
///
///
///
private int RuntimeConfInt(string param)
{
int answ = 0;
if (RuntimeConfDict.ContainsKey(param))
{
string retVal = RuntimeConfDict[param];
int.TryParse(retVal, out answ);
}
return answ;
}
///
/// Recupera parametro conf in Runtime di tipo Int
///
///
///
private string RuntimeConfString(string param)
{
string answ = "";
if (RuntimeConfDict.ContainsKey(param))
{
answ = RuntimeConfDict[param];
}
return answ;
}
#endregion Private Methods
}
}