From 518087289e3b798fd7b0f029fd366d80df81c43b Mon Sep 17 00:00:00 2001 From: Meik Date: Wed, 18 Mar 2026 15:03:49 +0100 Subject: [PATCH] Run diagnostics actions off UI thread --- LiamWorkflowDiagnostics/MainWindow.xaml.cs | 406 +++++++++++---------- 1 file changed, 217 insertions(+), 189 deletions(-) diff --git a/LiamWorkflowDiagnostics/MainWindow.xaml.cs b/LiamWorkflowDiagnostics/MainWindow.xaml.cs index 28a8b9d..1dfb6f3 100644 --- a/LiamWorkflowDiagnostics/MainWindow.xaml.cs +++ b/LiamWorkflowDiagnostics/MainWindow.xaml.cs @@ -180,12 +180,13 @@ namespace LiamWorkflowDiagnostics ApplyMatrix42Environment(ServerNameTextBox.Text, UseHttpsCheckBox.IsChecked ?? false); ApplyLicense(LicenseTextBox.Text); - _session = new ProviderTestSession(msg => AppendLog(msg)); - var success = await _session.InitializeAsync(providerData, maskToken, CreateProviderInstance, providerConfigClassId, providerConfigObjectId); + var session = new ProviderTestSession(msg => AppendLog(msg)); + _session = session; + var success = await Task.Run(() => session.InitializeAsync(providerData, maskToken, CreateProviderInstance, providerConfigClassId, providerConfigObjectId)); if (success) { AppendLog("Provider initialisiert und authentifiziert.", LogLevels.Info); - ResultTextBox.Text = _session.SanitizedConfigJson; + ResultTextBox.Text = session.SanitizedConfigJson; } else { @@ -556,14 +557,17 @@ namespace LiamWorkflowDiagnostics try { - var maxDepth = _session.Provider.MaxDepth; + var provider = _session.Provider; + var configurationId = !string.IsNullOrWhiteSpace(_session.ProviderConfigObjectId) + ? _session.ProviderConfigObjectId + : (_session.ProviderConfigId ?? string.Empty); + var runWhatIf = IsWhatIfEnabled; + var maxDepth = provider.MaxDepth; AppendLog($"Lese DataAreas (MaxDepth={maxDepth}) ..."); - var result = await LiamWorkflowRuntime.GetDataAreasFromProviderAsync( - _session.Provider, - !string.IsNullOrWhiteSpace(_session.ProviderConfigObjectId) - ? _session.ProviderConfigObjectId - : (_session.ProviderConfigId ?? string.Empty), - IsWhatIfEnabled); + var result = await Task.Run(() => LiamWorkflowRuntime.GetDataAreasFromProviderAsync( + provider, + configurationId, + runWhatIf)); ResultTextBox.Text = JsonConvert.SerializeObject(result, Formatting.Indented); if (!result.Success) @@ -578,7 +582,7 @@ namespace LiamWorkflowDiagnostics return; } - if (IsWhatIfEnabled && result.AutomaticEnsurePreview != null && result.AutomaticEnsurePreview.Count > 0) + if (runWhatIf && result.AutomaticEnsurePreview != null && result.AutomaticEnsurePreview.Count > 0) { AppendLog($"EnsureNtfsPermissionGroups wurde nur simuliert fuer {result.AutomaticEnsurePreview.Count} Ordner. Details stehen im Result-JSON.", LogLevels.Warning); } @@ -594,7 +598,7 @@ namespace LiamWorkflowDiagnostics private async void ExecuteNtfsCreateButton_Click(object sender, RoutedEventArgs e) { - await ExecuteProviderActionAsync("NTFS Folder Create", async () => + try { var provider = EnsureInitializedProvider("NTFS"); var folderPath = GetRequiredText(NtfsCreateFolderPathTextBox.Text, "New Folder Path"); @@ -611,53 +615,48 @@ namespace LiamWorkflowDiagnostics var readerSids = ParseIdentifierList(NtfsCreateReaderSidsTextBox.Text, "Reader SIDs"); var writerSids = ParseIdentifierList(NtfsCreateWriterSidsTextBox.Text, "Writer SIDs"); - var result = await LiamWorkflowRuntime.CreateDataAreaAsync( - provider, - folderPath, - parentPath, - null, - ownerSids, - readerSids, - writerSids); - - return new + await ExecuteProviderActionAsync("NTFS Folder Create", async () => { - result.Success, - ResultToken = MapResultToken(result.ResultToken) - }; - }, () => - { - var provider = EnsureInitializedProvider("NTFS"); - var folderPath = GetRequiredText(NtfsCreateFolderPathTextBox.Text, "New Folder Path"); - var parentPath = NormalizeOptionalText(NtfsCreateParentPathTextBox.Text); - if (string.IsNullOrWhiteSpace(parentPath)) - { - parentPath = Directory.GetParent(folderPath)?.FullName; - } - if (string.IsNullOrWhiteSpace(parentPath)) - throw new InvalidOperationException("Parent Folder Path konnte nicht ermittelt werden."); - var ownerSids = ParseIdentifierList(NtfsCreateOwnerSidsTextBox.Text, "Owner SIDs"); - if (ownerSids.Count == 0) - throw new InvalidOperationException("Owner SIDs: mindestens ein Eintrag ist fuer die Ordneranlage erforderlich."); + var result = await Task.Run(() => LiamWorkflowRuntime.CreateDataAreaAsync( + provider, + folderPath, + parentPath, + null, + ownerSids, + readerSids, + writerSids)); - return CreateWhatIfResult( - "NTFS Folder Create", - "Wuerde einen Ordner anlegen und fehlende Gruppen sowie ACLs sicherstellen. Es wurden keine Aenderungen ausgefuehrt.", - new + return new { - ProviderRootPath = provider.RootPath, - NewFolderPath = folderPath, - ParentFolderPath = parentPath, - OwnerSids = ownerSids, - ReaderSids = ParseIdentifierList(NtfsCreateReaderSidsTextBox.Text, "Reader SIDs"), - WriterSids = ParseIdentifierList(NtfsCreateWriterSidsTextBox.Text, "Writer SIDs") - }); - }); + result.Success, + ResultToken = MapResultToken(result.ResultToken) + }; + }, () => + { + return CreateWhatIfResult( + "NTFS Folder Create", + "Wuerde einen Ordner anlegen und fehlende Gruppen sowie ACLs sicherstellen. Es wurden keine Aenderungen ausgefuehrt.", + new + { + ProviderRootPath = provider.RootPath, + NewFolderPath = folderPath, + ParentFolderPath = parentPath, + OwnerSids = ownerSids, + ReaderSids = readerSids, + WriterSids = writerSids + }); + }); + } + catch (Exception ex) + { + AppendLog($"NTFS Folder Create fehlgeschlagen: {ex.Message}", LogLevels.Error); + MessageBox.Show(this, ex.ToString(), "NTFS Folder Create", MessageBoxButton.OK, MessageBoxImage.Error); + } } private async void ExecuteNtfsEnsureButton_Click(object sender, RoutedEventArgs e) { - await ExecuteProviderActionAsync("NTFS Ensure Groups / ACLs", async () => + try { var provider = EnsureInitializedProvider("NTFS"); var folderPath = GetRequiredText(NtfsEnsureFolderPathTextBox.Text, "Folder Path"); @@ -665,42 +664,49 @@ namespace LiamWorkflowDiagnostics var readerSids = ParseIdentifierList(NtfsEnsureReaderSidsTextBox.Text, "Reader SIDs"); var writerSids = ParseIdentifierList(NtfsEnsureWriterSidsTextBox.Text, "Writer SIDs"); var ensureTraverse = NtfsEnsureTraverseCheckBox.IsChecked ?? false; - var result = await LiamWorkflowRuntime.EnsureNtfsPermissionGroupsAsync( - provider, - folderPath, - null, - ownerSids, - readerSids, - writerSids, - ensureTraverse); - return new + await ExecuteProviderActionAsync("NTFS Ensure Groups / ACLs", async () => { - result.Success, - ResultToken = MapResultToken(result.ResultToken) - }; - }, () => - { - var provider = EnsureInitializedProvider("NTFS"); - var folderPath = GetRequiredText(NtfsEnsureFolderPathTextBox.Text, "Folder Path"); - return CreateWhatIfResult( - "NTFS Ensure Groups / ACLs", - "Wuerde fehlende NTFS-Berechtigungsgruppen und ACLs additiv sicherstellen. Es wurden keine Aenderungen ausgefuehrt.", - new + var result = await Task.Run(() => LiamWorkflowRuntime.EnsureNtfsPermissionGroupsAsync( + provider, + folderPath, + null, + ownerSids, + readerSids, + writerSids, + ensureTraverse)); + + return new { - ProviderRootPath = provider.RootPath, - FolderPath = folderPath, - OwnerSids = ParseIdentifierList(NtfsEnsureOwnerSidsTextBox.Text, "Owner SIDs"), - ReaderSids = ParseIdentifierList(NtfsEnsureReaderSidsTextBox.Text, "Reader SIDs"), - WriterSids = ParseIdentifierList(NtfsEnsureWriterSidsTextBox.Text, "Writer SIDs"), - EnsureTraverseGroups = NtfsEnsureTraverseCheckBox.IsChecked ?? false - }); - }); + result.Success, + ResultToken = MapResultToken(result.ResultToken) + }; + }, () => + { + return CreateWhatIfResult( + "NTFS Ensure Groups / ACLs", + "Wuerde fehlende NTFS-Berechtigungsgruppen und ACLs additiv sicherstellen. Es wurden keine Aenderungen ausgefuehrt.", + new + { + ProviderRootPath = provider.RootPath, + FolderPath = folderPath, + OwnerSids = ownerSids, + ReaderSids = readerSids, + WriterSids = writerSids, + EnsureTraverseGroups = ensureTraverse + }); + }); + } + catch (Exception ex) + { + AppendLog($"NTFS Ensure Groups / ACLs fehlgeschlagen: {ex.Message}", LogLevels.Error); + MessageBox.Show(this, ex.ToString(), "NTFS Ensure Groups / ACLs", MessageBoxButton.OK, MessageBoxImage.Error); + } } private async void ExecuteAdCreateButton_Click(object sender, RoutedEventArgs e) { - await ExecuteProviderActionAsync("AD Ensure Service Groups", async () => + try { var provider = EnsureInitializedProvider("Active Directory"); var serviceName = GetRequiredText(AdServiceNameTextBox.Text, "Service Name"); @@ -714,151 +720,171 @@ namespace LiamWorkflowDiagnostics var ownerSids = ParseIdentifierList(AdOwnerSidsTextBox.Text, "Owner SIDs"); var memberSids = ParseIdentifierList(AdMemberSidsTextBox.Text, "Member SIDs"); - var result = await Task.Run(() => LiamWorkflowRuntime.CreateAdServiceGroups( - provider, - serviceName, - description, - scope, - groupType, - ownerSids, - memberSids)); + await ExecuteProviderActionAsync("AD Ensure Service Groups", async () => + { + var result = await Task.Run(() => LiamWorkflowRuntime.CreateAdServiceGroups( + provider, + serviceName, + description, + scope, + groupType, + ownerSids, + memberSids)); - return result; - }, () => + return result; + }, () => + { + return CreateWhatIfResult( + "AD Ensure Service Groups", + "Wuerde Service-Gruppen im Active Directory anhand der Namenskonvention sicherstellen. Es wurden keine Aenderungen ausgefuehrt.", + new + { + ServiceName = serviceName, + Description = description, + Scope = scope.ToString(), + GroupType = groupType.ToString(), + OwnerSids = ownerSids, + MemberSids = memberSids + }); + }); + } + catch (Exception ex) { - _ = EnsureInitializedProvider("Active Directory"); - var serviceName = GetRequiredText(AdServiceNameTextBox.Text, "Service Name"); - var description = NormalizeOptionalText(AdDescriptionTextBox.Text); - var scope = AdScopeComboBox.SelectedItem is eLiamAccessRoleScopes selectedScope - ? selectedScope - : eLiamAccessRoleScopes.Universal; - var groupType = AdGroupTypeComboBox.SelectedItem is ADServiceGroupCreator.ADGroupType selectedType - ? selectedType - : ADServiceGroupCreator.ADGroupType.Distribution; - - return CreateWhatIfResult( - "AD Ensure Service Groups", - "Wuerde Service-Gruppen im Active Directory anhand der Namenskonvention sicherstellen. Es wurden keine Aenderungen ausgefuehrt.", - new - { - ServiceName = serviceName, - Description = description, - Scope = scope.ToString(), - GroupType = groupType.ToString(), - OwnerSids = ParseIdentifierList(AdOwnerSidsTextBox.Text, "Owner SIDs"), - MemberSids = ParseIdentifierList(AdMemberSidsTextBox.Text, "Member SIDs") - }); - }); + AppendLog($"AD Ensure Service Groups fehlgeschlagen: {ex.Message}", LogLevels.Error); + MessageBox.Show(this, ex.ToString(), "AD Ensure Service Groups", MessageBoxButton.OK, MessageBoxImage.Error); + } } private async void ExecuteMsTeamsCloneButton_Click(object sender, RoutedEventArgs e) { - await ExecuteProviderActionAsync("MsTeams Clone Team", async () => + try { var provider = EnsureInitializedProvider("MsTeams"); var sourceTeamId = GetRequiredText(MsTeamsSourceTeamIdTextBox.Text, "Source Team ID"); var newTeamName = GetRequiredText(MsTeamsNewNameTextBox.Text, "New Team Name"); + var description = NormalizeOptionalText(MsTeamsDescriptionTextBox.Text); var visibility = GetSelectedMsTeamsVisibility(); + var partsToClone = GetSelectedCloneParts(); var additionalMembers = ParseIdentifierList(MsTeamsAdditionalMembersTextBox.Text, "Additional Members"); var additionalOwners = ParseIdentifierList(MsTeamsAdditionalOwnersTextBox.Text, "Additional Owners"); - var result = await LiamWorkflowRuntime.CloneTeamAsync( - provider, - sourceTeamId, - newTeamName, - NormalizeOptionalText(MsTeamsDescriptionTextBox.Text), - visibility, - GetSelectedCloneParts(), - string.Join(";", additionalMembers), - string.Join(";", additionalOwners)); + await ExecuteProviderActionAsync("MsTeams Clone Team", async () => + { + var result = await Task.Run(() => LiamWorkflowRuntime.CloneTeamAsync( + provider, + sourceTeamId, + newTeamName, + description, + visibility, + partsToClone, + string.Join(";", additionalMembers), + string.Join(";", additionalOwners))); - return result; - }, () => + return result; + }, () => + { + return CreateWhatIfResult( + "MsTeams Clone Team", + "Wuerde ein Team anhand der gewaehlten Clone-Bestandteile klonen. Es wurden keine Aenderungen ausgefuehrt.", + new + { + SourceTeamId = sourceTeamId, + NewTeamName = newTeamName, + Description = description, + Visibility = visibility, + PartsToClone = partsToClone, + AdditionalMembers = additionalMembers, + AdditionalOwners = additionalOwners + }); + }); + } + catch (Exception ex) { - _ = EnsureInitializedProvider("MsTeams"); - var sourceTeamId = GetRequiredText(MsTeamsSourceTeamIdTextBox.Text, "Source Team ID"); - var newTeamName = GetRequiredText(MsTeamsNewNameTextBox.Text, "New Team Name"); - - return CreateWhatIfResult( - "MsTeams Clone Team", - "Wuerde ein Team anhand der gewaehlten Clone-Bestandteile klonen. Es wurden keine Aenderungen ausgefuehrt.", - new - { - SourceTeamId = sourceTeamId, - NewTeamName = newTeamName, - Description = NormalizeOptionalText(MsTeamsDescriptionTextBox.Text), - Visibility = GetSelectedMsTeamsVisibility(), - PartsToClone = GetSelectedCloneParts(), - AdditionalMembers = ParseIdentifierList(MsTeamsAdditionalMembersTextBox.Text, "Additional Members"), - AdditionalOwners = ParseIdentifierList(MsTeamsAdditionalOwnersTextBox.Text, "Additional Owners") - }); - }); + AppendLog($"MsTeams Clone Team fehlgeschlagen: {ex.Message}", LogLevels.Error); + MessageBox.Show(this, ex.ToString(), "MsTeams Clone Team", MessageBoxButton.OK, MessageBoxImage.Error); + } } private async void ExecuteExchangeMailboxButton_Click(object sender, RoutedEventArgs e) { - await ExecuteProviderActionAsync("Exchange Create Shared Mailbox", async () => + try { var provider = EnsureInitializedProvider("Exchange"); var name = GetRequiredText(ExchangeMailboxNameTextBox.Text, "Name"); var alias = GetRequiredText(ExchangeMailboxAliasTextBox.Text, "Alias"); var displayName = NormalizeOptionalText(ExchangeMailboxDisplayNameTextBox.Text); var primarySmtp = NormalizeOptionalText(ExchangeMailboxPrimarySmtpTextBox.Text); - var result = await Task.Run(() => LiamWorkflowRuntime.CreateSharedMailbox( - provider, - name, - alias, - displayName, - primarySmtp)); - return result; - }, () => + await ExecuteProviderActionAsync("Exchange Create Shared Mailbox", async () => + { + var result = await Task.Run(() => LiamWorkflowRuntime.CreateSharedMailbox( + provider, + name, + alias, + displayName, + primarySmtp)); + + return result; + }, () => + { + return CreateWhatIfResult( + "Exchange Create Shared Mailbox", + "Wuerde eine Shared Mailbox inklusive Ownership-Gruppen erzeugen. Es wurden keine Aenderungen ausgefuehrt.", + new + { + Name = name, + Alias = alias, + DisplayName = displayName, + PrimarySmtpAddress = primarySmtp + }); + }); + } + catch (Exception ex) { - _ = EnsureInitializedProvider("Exchange"); - return CreateWhatIfResult( - "Exchange Create Shared Mailbox", - "Wuerde eine Shared Mailbox inklusive Ownership-Gruppen erzeugen. Es wurden keine Aenderungen ausgefuehrt.", - new - { - Name = GetRequiredText(ExchangeMailboxNameTextBox.Text, "Name"), - Alias = GetRequiredText(ExchangeMailboxAliasTextBox.Text, "Alias"), - DisplayName = NormalizeOptionalText(ExchangeMailboxDisplayNameTextBox.Text), - PrimarySmtpAddress = NormalizeOptionalText(ExchangeMailboxPrimarySmtpTextBox.Text) - }); - }); + AppendLog($"Exchange Create Shared Mailbox fehlgeschlagen: {ex.Message}", LogLevels.Error); + MessageBox.Show(this, ex.ToString(), "Exchange Create Shared Mailbox", MessageBoxButton.OK, MessageBoxImage.Error); + } } private async void ExecuteExchangeDistributionButton_Click(object sender, RoutedEventArgs e) { - await ExecuteProviderActionAsync("Exchange Create Distribution Group", async () => + try { var provider = EnsureInitializedProvider("Exchange"); var name = GetRequiredText(ExchangeDistributionNameTextBox.Text, "Name"); var alias = GetRequiredText(ExchangeDistributionAliasTextBox.Text, "Alias"); var displayName = NormalizeOptionalText(ExchangeDistributionDisplayNameTextBox.Text); var primarySmtp = NormalizeOptionalText(ExchangeDistributionPrimarySmtpTextBox.Text); - var result = await Task.Run(() => LiamWorkflowRuntime.CreateDistributionGroup( - provider, - name, - alias, - displayName, - primarySmtp)); - return result; - }, () => + await ExecuteProviderActionAsync("Exchange Create Distribution Group", async () => + { + var result = await Task.Run(() => LiamWorkflowRuntime.CreateDistributionGroup( + provider, + name, + alias, + displayName, + primarySmtp)); + + return result; + }, () => + { + return CreateWhatIfResult( + "Exchange Create Distribution Group", + "Wuerde eine Distribution Group inklusive Ownership-Gruppen erzeugen. Es wurden keine Aenderungen ausgefuehrt.", + new + { + Name = name, + Alias = alias, + DisplayName = displayName, + PrimarySmtpAddress = primarySmtp + }); + }); + } + catch (Exception ex) { - _ = EnsureInitializedProvider("Exchange"); - return CreateWhatIfResult( - "Exchange Create Distribution Group", - "Wuerde eine Distribution Group inklusive Ownership-Gruppen erzeugen. Es wurden keine Aenderungen ausgefuehrt.", - new - { - Name = GetRequiredText(ExchangeDistributionNameTextBox.Text, "Name"), - Alias = GetRequiredText(ExchangeDistributionAliasTextBox.Text, "Alias"), - DisplayName = NormalizeOptionalText(ExchangeDistributionDisplayNameTextBox.Text), - PrimarySmtpAddress = NormalizeOptionalText(ExchangeDistributionPrimarySmtpTextBox.Text) - }); - }); + AppendLog($"Exchange Create Distribution Group fehlgeschlagen: {ex.Message}", LogLevels.Error); + MessageBox.Show(this, ex.ToString(), "Exchange Create Distribution Group", MessageBoxButton.OK, MessageBoxImage.Error); + } } private async void FetchSecurityGroupsButton_Click(object sender, RoutedEventArgs e) @@ -871,8 +897,10 @@ namespace LiamWorkflowDiagnostics try { - AppendLog($"Lese SecurityGroups (Filter='{_session.Provider.GroupFilter}') ..."); - var result = await LiamWorkflowRuntime.GetSecurityGroupsFromProviderAsync(_session.Provider); + var provider = _session.Provider; + var filter = provider.GroupFilter; + AppendLog($"Lese SecurityGroups (Filter='{filter}') ..."); + var result = await Task.Run(() => LiamWorkflowRuntime.GetSecurityGroupsFromProviderAsync(provider)); ResultTextBox.Text = JsonConvert.SerializeObject(result, Formatting.Indented); if (!result.Success) @@ -936,7 +964,7 @@ namespace LiamWorkflowDiagnostics ? $"{actionName} im WhatIf-Modus gestartet. Schreibende Aenderungen werden nur simuliert." : $"{actionName} gestartet."); var result = runInWhatIfMode - ? whatIfAction() + ? await Task.Run(whatIfAction) : await action(); ResultTextBox.Text = JsonConvert.SerializeObject(result, Formatting.Indented); if (TryGetSuccessFlag(result, out var success) && !success)