using C4IT.F4SD.DisplayFormatting; using C4IT.FASD.Base; using C4IT.FASD.Cockpit.Communication; using C4IT.Logging; using C4IT.MultiLanguage; using FasdCockpitBase.Models; using FasdDesktopUi.Basics.Models; using FasdDesktopUi.Basics.Services.ProtocollService; using Newtonsoft.Json; using System; using System.Collections.Generic; using System.Linq; using System.Reflection; using System.Text; using System.Threading; using System.Threading.Tasks; using static C4IT.Logging.cLogManager; using static FasdDesktopUi.Basics.Models.cQuickActionStatusMonitorModel.cQuickActionStep; using static FasdDesktopUi.Basics.UserControls.QuickActionStatusMonitor; namespace FasdDesktopUi.Basics.UiActions { public class cUiRemoteQuickAction : cUiQuickAction { public cF4sdQuickActionRemote RemoteQuickAction { get; set; } public cUiRemoteQuickAction(cF4sdQuickActionRemote quickAction) : base(quickAction) { RemoteQuickAction = quickAction; } public async override Task GetQuickActionStatusMonitorDataAsync() { var scriptInfos = await cFasdCockpitCommunicationBase.Instance.GetQuickActionOfAgent(RemoteQuickAction.AgentScriptId); var actionSteps = new List() { new cQuickActionStatusMonitorModel.cQuickActionStep(cMultiLanguageSupport.GetItem("QuickAction.Remote.Connect"), RemoteQuickAction.Name, enumActionStepType.connectingToClient) }; if (scriptInfos.UserPermissionRequired) actionSteps.Add(new cQuickActionStatusMonitorModel.cQuickActionStep(cMultiLanguageSupport.GetItem("QuickAction.Remote.UserAcceptance"), RemoteQuickAction.Name, enumActionStepType.waitingForUserAcceptance)); actionSteps.Add(new cQuickActionStatusMonitorModel.cQuickActionStep(cMultiLanguageSupport.GetItem("QuickAction.Remote.Running"), RemoteQuickAction.Name, enumActionStepType.running)); return new cQuickActionStatusMonitorModel() { ActionName = RemoteQuickAction.Names.GetValue(), QuickActionDefinition = RemoteQuickAction, RequiresUserPermission = scriptInfos != null && scriptInfos.UserPermissionRequired, ActionSteps = actionSteps, QuickActionParameters = RemoteQuickAction.AdjustableParameters, RunQuickAction = ProcessActionAsync }; } public override async Task GetQuickActionDataAsync(cSupportCaseDataProvider dataProvider, bool isDetailedLayout) { DataProvider = dataProvider; var detailedData = new cDetailedDataModel() { Heading = cMultiLanguageSupport.GetItem("DetailsPage.History") }; //Get QuickAciton Data if (isDetailedLayout) { detailedData.FullDetailedData = new List() { new List() { "Status", cMultiLanguageSupport.GetItem("QuickAction.Revision.ExecutionTime") } }; var quickActionHistory = await dataProvider.QuickActionProtocollHelper.GetQuickActionHistoryAsync(RemoteQuickAction.Name); foreach (var quickActionLine in quickActionHistory) { quickActionLine[1] = cUtility.RawValueFormatter.GetDisplayValue(quickActionLine[1], RawValueType.DATETIME); detailedData.FullDetailedData.Add(quickActionLine); } } else detailedData.FullDetailedData = new List(); //Get Process Steps of Action var quickActionData = await GetQuickActionStatusMonitorDataAsync(); //Get Recommendation cRecommendationDataModel recommendationData = QuickActionRecommendation?.Recommendation != null ? QuickActionRecommendation : null; return new cDataCanvasDataModel() { DetailedData = detailedData, QuickActionStatusMonitorData = quickActionData, RecommendationData = recommendationData }; } public override async Task> ProcessActionAsync(CancellationToken token, Dictionary ParameterDictionary = null) { try { int agentDeviceId = int.MinValue; int? agentUserIdNullable = null; var startTime = DateTime.UtcNow; if (DataProvider.NamedParameterEntries.TryGetValue("AgentDeviceId", out var agentDeviceIdParameter)) _ = int.TryParse(agentDeviceIdParameter.GetValue(), out agentDeviceId); if (RemoteQuickAction.InformationClasses.Contains(enumFasdInformationClass.User)) if (DataProvider.NamedParameterEntries.TryGetValue("AgentUserId", out var agentUserIdParameter)) if (int.TryParse(agentUserIdParameter.GetValue(), out int agentUserId)) agentUserIdNullable = agentUserId; //todo: task of DataProviderBase? var QuickActionResult = new cF4sdQuickActionRevision(); if (cCockpitConfiguration.Instance.agentApiConfiguration.OrganizationCode != null) { var parameters = cExternalToolExecutorEnh.ReplaceParameters(RemoteQuickAction.Parameters, DataProvider.NamedParameterEntries.ToInterfaceDictionary(), false, ParameterDictionary); var scriptInformation = await cFasdCockpitCommunicationBase.Instance.RunAgentScript(RemoteQuickAction, cCockpitConfiguration.Instance.agentApiConfiguration.OrganizationCode.Value, agentDeviceId, agentUserIdNullable, parameters); await UpdateQuickActionStatusAsync(scriptInformation.TaskId, token); QuickActionResult = await GetRevisionForStatusMonitorAsync(scriptInformation.RevisionId, scriptInformation.TaskId, token); if (QuickActionResult != null && QuickActionResult.Status is enumQuickActionRevisionStatus.finishedWithError) { if (QuickActionResult.Output == null) QuickActionResult.Output = new cF4sdQuickActionRevision.cOutput() { ErrorCode = 1, ErrorDescription = QuickActionResult.OutputText }; if (QuickActionResult.Output.ErrorCode == null && QuickActionResult.Output.ResultCode == 0 && QuickActionResult.Output.ErrorDescription == null && !string.IsNullOrEmpty(QuickActionResult.OutputText)) QuickActionResult.Output.ErrorDescription = QuickActionResult.OutputText; } } if (QuickActionResult == null) QuickActionResult = new cF4sdQuickActionRevision() { Status = enumQuickActionRevisionStatus.finishedWithError, OutputText = cMultiLanguageSupport.GetItem("QuickAction.Revision.Status.Canceled") }; if (QuickActionResult.Measures?.Count > 0) { var StatusMonitorMeasureValues = GetStatusMonitorMeasureValues(QuickActionResult.Measures, RemoteQuickAction.QuickActionMeasures); if (StatusMonitorMeasureValues?.Count > 0) StatusMonitor.MeasureValues = StatusMonitorMeasureValues; } var quickActionOutput = cQuickActionOutput.GetQuickActionOutput(QuickActionResult.Output, DataProvider); var protocollOutput = cQuickActionOutput.GetQuickActionOutput(QuickActionResult.Output, DataProvider); if (!token.IsCancellationRequested) { StatusMonitor.QuickActionOutputs.Add(QuickActionResult.Output); var status = quickActionOutput?.IsError == true ? enumQuickActionRevisionStatus.finishedWithError : QuickActionResult.Status; cQuickActionStatusMonitorModel.cQuickActionStep.SetQuickActionStepStatuses(StatusMonitor.QuickActionData.ActionSteps, RemoteQuickAction.Name, enumActionStepType.running, status); cQuickActionStatusMonitorModel.cQuickActionStep.SetQuickActionStepStatuses(StatusMonitor.QuickActionData.ActionSteps, RemoteQuickAction.Name, enumActionStepType.main, status); cQuickActionCopyData copyData = QuickActionProtocollEntry.GetCopyData(RemoteQuickAction, DataProvider, true, protocollOutput, StatusMonitor.MeasureValues); F4SDProtocoll.Instance.Add(new QuickActionProtocollEntry(RemoteQuickAction, copyData)); } else { cQuickActionStatusMonitorModel.cQuickActionStep.CancelRemainingQuickActionSteps(StatusMonitor.QuickActionData.ActionSteps); quickActionOutput = new cQuickActionOutputSingle(new cF4sdQuickActionRevision.cOutput() { ResultCode = enumQuickActionSuccess.error, ErrorDescription = cMultiLanguageSupport.GetItem("QuickAction.Copy.Output.Cancel") }); if (cF4SDCockpitXmlConfig.Instance.HealthCardConfig.ProtocollLanguage != null) { string tempLang = cMultiLanguageSupport.CurrentLanguage; cMultiLanguageSupport.CurrentLanguage = cF4SDCockpitXmlConfig.Instance.HealthCardConfig.ProtocollLanguage; protocollOutput = new cQuickActionOutputSingle(new cF4sdQuickActionRevision.cOutput() { ResultCode = enumQuickActionSuccess.error, ErrorDescription = cMultiLanguageSupport.GetItem("QuickAction.Copy.Output.Cancel") }); cMultiLanguageSupport.CurrentLanguage = tempLang; } cQuickActionCopyData copyData = QuickActionProtocollEntry.GetCopyData(RemoteQuickAction, DataProvider, true, protocollOutput, StatusMonitor.MeasureValues); F4SDProtocoll.Instance.Add(new QuickActionProtocollEntry(RemoteQuickAction, copyData)); return new List() { cMultiLanguageSupport.GetItem("QuickAction.Revision.Status.Canceled"), cUtility.RawValueFormatter.GetDisplayValue(DateTime.UtcNow, RawValueType.DATETIME) }; } string quickActionStatus; switch (QuickActionResult.Status) { case enumQuickActionRevisionStatus.inProgress: quickActionStatus = cMultiLanguageSupport.GetItem("QuickAction.Revision.Status.InProgress"); break; case enumQuickActionRevisionStatus.finishedSuccessfull: quickActionStatus = cMultiLanguageSupport.GetItem("QuickAction.Revision.Status.FinishedSuccessfull"); break; case enumQuickActionRevisionStatus.finishedWithError: quickActionStatus = cMultiLanguageSupport.GetItem("QuickAction.Revision.Status.FinishedWithError"); break; case enumQuickActionRevisionStatus.unknown: default: quickActionStatus = cMultiLanguageSupport.GetItem("QuickAction.Revision.Status.Unknown"); break; } _ = Task.Run(async () => { try { Guid? userId = DataProvider?.Identities?.FirstOrDefault(identity => identity.Class == enumFasdInformationClass.User)?.Id; Guid? computerId = DataProvider?.Identities?.FirstOrDefault(identity => identity.Class == enumFasdInformationClass.Computer)?.Id; var reportQuickActionParameter = new cF4SDQuickActionParameters() { CaseId = DataProvider.CaseId, QuickActionId = RemoteQuickAction.Id, QuickActionName = RemoteQuickAction.Name, Paramaters = ParameterDictionary is null ? null : JsonConvert.SerializeObject(ParameterDictionary, Formatting.None), Result = QuickActionResult.Output.Values is null ? null : JsonConvert.SerializeObject(QuickActionResult.Output.Values, Formatting.None), ErrorCode = QuickActionResult.Output.ErrorCode, ErrorDescription = QuickActionResult.Output.ErrorDescription, Start = startTime, Finish = DateTime.UtcNow, UserId = userId, DeviceId = computerId, ExecutionType = RemoteQuickAction.ExecutionType, ResultType = RemoteQuickAction.ResultType }; var reportedQuickActionSuccessfully = await cFasdCockpitCommunicationBase.Instance.ReportQuickAction(reportQuickActionParameter); if (reportedQuickActionSuccessfully is false) LogEntry($"Failed to report QuickAction '{RemoteQuickAction.Name}' for case '{reportQuickActionParameter.CaseId}' to Analytics.", LogLevels.Warning); } catch (Exception E) { LogException(E); } }); return new List() { quickActionStatus, cUtility.RawValueFormatter.GetDisplayValue(DateTime.UtcNow, RawValueType.DATETIME) }; } catch (Exception E) { LogException(E); return new List() { cMultiLanguageSupport.GetItem("QuickAction.Revision.Status.FinishedWithError"), cUtility.RawValueFormatter.GetDisplayValue(DateTime.UtcNow, RawValueType.DATETIME) }; } } public static List GetStatusMonitorMeasureValues(List measures, Dictionary QuickActionMeasures) { try { var output = new List(); if (QuickActionMeasures == null || measures == null) return null; foreach (var measure in measures) { if (!QuickActionMeasures.TryGetValue(measure.Id, out var measureDefinition)) continue; output.Add(new cQuickActionMeasureValue() { Id = measure.Id, Names = measureDefinition.Names, Display = cUtility.GetRawValueType(measureDefinition.Display), Value = measure.Value, PostValue = measure.PostValue }); } return output; } catch (Exception E) { LogException(E); } finally { } return null; } private async Task UpdateQuickActionStatusAsync(int taskId, CancellationToken token) { try { const int pollDelayInMilliseconds = 250; while (!token.IsCancellationRequested) { var quickActionStatus = await cFasdCockpitCommunicationBase.Instance.GetAgentQuickActionStatus(taskId); if (quickActionStatus == enumQuickActionStatus.Unknown) break; List actionStepsToUpdate = new List(); switch (quickActionStatus) { case enumQuickActionStatus.ConnectingToClient: break; case enumQuickActionStatus.WaitingForUserAcceptance: actionStepsToUpdate = new List() { enumActionStepType.connectingToClient }; break; case enumQuickActionStatus.Running: case enumQuickActionStatus.Finished: actionStepsToUpdate = new List() { enumActionStepType.connectingToClient, enumActionStepType.waitingForUserAcceptance }; break; case enumQuickActionStatus.Cancelled: var remainingSteps = StatusMonitor.QuickActionData.ActionSteps.Where(step => step.Status != enumQuickActionRevisionStatus.finishedSuccessfull); foreach (var remainingStep in remainingSteps) { remainingStep.Status = enumQuickActionRevisionStatus.canceled; } break; } foreach (var actionStepToUpdate in actionStepsToUpdate) { cQuickActionStatusMonitorModel.cQuickActionStep.SetQuickActionStepStatuses(StatusMonitor.QuickActionData.ActionSteps, RemoteQuickAction.Name, actionStepToUpdate, enumQuickActionRevisionStatus.finishedSuccessfull); } if (quickActionStatus == enumQuickActionStatus.Finished || quickActionStatus == enumQuickActionStatus.Cancelled) break; await Task.Delay(pollDelayInMilliseconds); } } catch (Exception E) { LogException(E); } } private async Task GetRevisionForStatusMonitorAsync(int revisionId, int taskId, CancellationToken token) { try { if (!token.IsCancellationRequested) { var revision = await cFasdCockpitCommunicationBase.Instance.GetAgentRevision(revisionId, cCockpitConfiguration.Instance.agentApiConfiguration.OrganizationCode.Value); return revision; } else await cFasdCockpitCommunicationBase.Instance.CancelAgentTask(taskId); } catch (Exception E) { LogException(E); } return null; } } }