From 27299fc8e753071164dc50e17ccb3c617108188e Mon Sep 17 00:00:00 2001 From: Johannes Rest Date: Mon, 1 Jun 2026 15:26:47 +0200 Subject: [PATCH] Fixed some UI layout stuff. --- Dokumentation.md | 3 + README.md | 4 + .../Ui/MainForm.cs | 120 ++++++++++++++---- 3 files changed, 105 insertions(+), 22 deletions(-) diff --git a/Dokumentation.md b/Dokumentation.md index 1df54e3..15d07e1 100644 --- a/Dokumentation.md +++ b/Dokumentation.md @@ -35,6 +35,8 @@ Das BizTalk Platform Management Tool unterstützt kontrollierte Wartungsfenster 8. Nach der Wartung mit **Restore** aus `before.json` wiederherstellen. 9. Mit **Snapshot After** und **Compare** die Umgebung validieren. +Die Statusanzeige rechts im Kopfbereich bewertet die Host-Instance-Zustaende des letzten Snapshots und zeigt `Started`, `Stopped`, `Partial` oder `Unknown`. **Clear** leert die sichtbaren Ergebnis- und Log-Grids, loescht aber keine Dateien. **Close** beendet die Anwendung. + ## Sicherheitsdesign - Dry-run ist standardmäßig aktiviert. @@ -42,6 +44,7 @@ Das BizTalk Platform Management Tool unterstützt kontrollierte Wartungsfenster - Jede Operation schreibt Einträge in das sichtbare Operation Log. - Zusätzlich wird neben der EXE eine tägliche Logdatei `BizTalkPlatformManagementTool-yyyy-MM-dd.log` geschrieben. - Logdateien werden rollierend für den aktuellen Tag plus vier vorherige Tage vorgehalten. +- Der Kopfbereich zeigt den zuletzt erkannten Umgebungsstatus aus den Host Instances. - Operationspläne werden vor Laufzeitänderungen gespeichert. - WMI-Methodenrückgaben werden geprüft. - Wartezeiten nutzen konfigurierbare Timeout- und Polling-Werte. diff --git a/README.md b/README.md index 8920472..d75cf80 100644 --- a/README.md +++ b/README.md @@ -21,6 +21,8 @@ WinForms tool for controlled Microsoft BizTalk Server 2020 platform operations d - Dry-run mode enabled by default - WMI access through `root\MicrosoftBizTalkServer` - Detailed operation logging in the GUI and daily rolling log files next to the executable +- Environment status indicator based on host instance state +- Clear and Close actions in the main toolbar - No compile-time dependency on BizTalk ExplorerOM assemblies ## Safe Usage @@ -34,6 +36,8 @@ WinForms tool for controlled Microsoft BizTalk Server 2020 platform operations d 7. After maintenance, click **Restore** using the saved `before.json`. 8. Click **Snapshot After** and **Compare**. +The environment indicator shows `Started`, `Stopped`, `Partial` or `Unknown` from the most recent snapshot. `Clear` removes the visible status and operation log grids; it does not delete files. + ## Operation Order Shutdown: diff --git a/src/BizTalkPlatformManagementTool/Ui/MainForm.cs b/src/BizTalkPlatformManagementTool/Ui/MainForm.cs index c1fbf9f..17d52dd 100644 --- a/src/BizTalkPlatformManagementTool/Ui/MainForm.cs +++ b/src/BizTalkPlatformManagementTool/Ui/MainForm.cs @@ -1,6 +1,7 @@ using System; using System.Drawing; using System.IO; +using System.Linq; using System.Threading.Tasks; using System.Windows.Forms; using BizTalkPlatformManagementTool.Models; @@ -20,6 +21,7 @@ namespace BizTalkPlatformManagementTool.Ui private readonly DataGridView _logGrid = new DataGridView(); private readonly StatusStrip _statusStrip = new StatusStrip(); private readonly ToolStripStatusLabel _statusLabel = new ToolStripStatusLabel(); + private readonly Label _environmentStatusLabel = new Label(); private readonly OperationLogger _logger; private readonly BizTalkOperationService _service; @@ -29,6 +31,8 @@ namespace BizTalkPlatformManagementTool.Ui private Button _compareButton; private Button _shutdownButton; private Button _restoreButton; + private Button _clearButton; + private Button _closeButton; public MainForm() { @@ -53,7 +57,7 @@ namespace BizTalkPlatformManagementTool.Ui RowCount = 4, Padding = new Padding(10) }; - root.RowStyles.Add(new RowStyle(SizeType.Absolute, 88)); + root.RowStyles.Add(new RowStyle(SizeType.Absolute, 92)); root.RowStyles.Add(new RowStyle(SizeType.Absolute, 54)); root.RowStyles.Add(new RowStyle(SizeType.Percent, 100)); root.RowStyles.Add(new RowStyle(SizeType.Absolute, 24)); @@ -70,42 +74,52 @@ namespace BizTalkPlatformManagementTool.Ui private Control BuildSettingsPanel() { - var panel = new TableLayoutPanel { Dock = DockStyle.Fill, ColumnCount = 8, RowCount = 2 }; - panel.ColumnStyles.Add(new ColumnStyle(SizeType.Absolute, 70)); + var panel = new TableLayoutPanel { Dock = DockStyle.Fill, ColumnCount = 10, RowCount = 2 }; + panel.ColumnStyles.Add(new ColumnStyle(SizeType.Absolute, 64)); panel.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 30)); + panel.ColumnStyles.Add(new ColumnStyle(SizeType.Absolute, 64)); + panel.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 45)); + panel.ColumnStyles.Add(new ColumnStyle(SizeType.Absolute, 96)); + panel.ColumnStyles.Add(new ColumnStyle(SizeType.Absolute, 70)); panel.ColumnStyles.Add(new ColumnStyle(SizeType.Absolute, 76)); - panel.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 35)); - panel.ColumnStyles.Add(new ColumnStyle(SizeType.Absolute, 88)); - panel.ColumnStyles.Add(new ColumnStyle(SizeType.Absolute, 82)); panel.ColumnStyles.Add(new ColumnStyle(SizeType.Absolute, 72)); - panel.ColumnStyles.Add(new ColumnStyle(SizeType.Absolute, 88)); - panel.RowStyles.Add(new RowStyle(SizeType.Absolute, 36)); - panel.RowStyles.Add(new RowStyle(SizeType.Absolute, 36)); + panel.ColumnStyles.Add(new ColumnStyle(SizeType.Absolute, 76)); + panel.ColumnStyles.Add(new ColumnStyle(SizeType.Absolute, 220)); + panel.RowStyles.Add(new RowStyle(SizeType.Absolute, 40)); + panel.RowStyles.Add(new RowStyle(SizeType.Absolute, 40)); _serverTextBox.Text = Environment.MachineName; - _serverTextBox.Dock = DockStyle.Fill; + ConfigureInput(_serverTextBox); _outputTextBox.Text = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory), "BizTalkPlatformManagementTool"); - _outputTextBox.Dock = DockStyle.Fill; + ConfigureInput(_outputTextBox); _stateFileTextBox.Text = "before.json"; - _stateFileTextBox.Dock = DockStyle.Fill; + ConfigureInput(_stateFileTextBox); _timeoutInput.Minimum = 30; _timeoutInput.Maximum = 3600; _timeoutInput.Value = 300; - _timeoutInput.Dock = DockStyle.Fill; + ConfigureInput(_timeoutInput); _pollInput.Minimum = 1; _pollInput.Maximum = 60; _pollInput.Value = 5; - _pollInput.Dock = DockStyle.Fill; + ConfigureInput(_pollInput); _dryRunCheckBox.Text = "Dry run"; _dryRunCheckBox.Checked = true; _dryRunCheckBox.Dock = DockStyle.Fill; + _dryRunCheckBox.Margin = new Padding(8, 7, 8, 7); + _dryRunCheckBox.TextAlign = ContentAlignment.MiddleLeft; - var browseButton = new Button { Text = "Browse...", Dock = DockStyle.Fill }; + var browseButton = new Button { Text = "Browse...", Dock = DockStyle.Fill, Margin = new Padding(8, 5, 8, 5) }; browseButton.Click += BrowseButtonClick; + _environmentStatusLabel.Dock = DockStyle.Fill; + _environmentStatusLabel.Margin = new Padding(12, 5, 0, 5); + _environmentStatusLabel.TextAlign = ContentAlignment.MiddleCenter; + _environmentStatusLabel.BorderStyle = BorderStyle.FixedSingle; + UpdateEnvironmentStatus(null); + panel.Controls.Add(Label("Server"), 0, 0); panel.Controls.Add(_serverTextBox, 1, 0); panel.Controls.Add(Label("Output"), 2, 0); @@ -116,23 +130,27 @@ namespace BizTalkPlatformManagementTool.Ui panel.Controls.Add(Label("State"), 0, 1); panel.Controls.Add(_stateFileTextBox, 1, 1); - panel.SetColumnSpan(_stateFileTextBox, 3); - panel.Controls.Add(_dryRunCheckBox, 4, 1); - panel.Controls.Add(Label("Poll sec."), 5, 1); - panel.Controls.Add(_pollInput, 6, 1); + panel.SetColumnSpan(_stateFileTextBox, 2); + panel.Controls.Add(_dryRunCheckBox, 3, 1); + panel.Controls.Add(Label("Poll sec."), 7, 1); + panel.Controls.Add(_pollInput, 8, 1); + panel.Controls.Add(_environmentStatusLabel, 9, 0); + panel.SetRowSpan(_environmentStatusLabel, 2); return panel; } private Control BuildActionPanel() { - var panel = new FlowLayoutPanel { Dock = DockStyle.Fill, FlowDirection = FlowDirection.LeftToRight, Padding = new Padding(0, 8, 0, 0) }; + var panel = new FlowLayoutPanel { Dock = DockStyle.Fill, FlowDirection = FlowDirection.LeftToRight, Padding = new Padding(0, 8, 0, 0), WrapContents = false }; _diagnoseButton = ActionButton("Diagnose", DiagnoseClick); _beforeButton = ActionButton("Snapshot Before", BeforeClick); _afterButton = ActionButton("Snapshot After", AfterClick); _compareButton = ActionButton("Compare", CompareClick); _shutdownButton = ActionButton("Shutdown", ShutdownClick); _restoreButton = ActionButton("Restore", RestoreClick); + _clearButton = ActionButton("Clear", ClearClick); + _closeButton = ActionButton("Close", CloseClick); panel.Controls.Add(_diagnoseButton); panel.Controls.Add(_beforeButton); @@ -140,6 +158,8 @@ namespace BizTalkPlatformManagementTool.Ui panel.Controls.Add(_compareButton); panel.Controls.Add(_shutdownButton); panel.Controls.Add(_restoreButton); + panel.Controls.Add(_clearButton); + panel.Controls.Add(_closeButton); return panel; } @@ -259,6 +279,19 @@ namespace BizTalkPlatformManagementTool.Ui }); } + private void ClearClick(object sender, EventArgs e) + { + _statusGrid.Rows.Clear(); + _logGrid.Rows.Clear(); + UpdateEnvironmentStatus(null); + _statusLabel.Text = "Ready."; + } + + private void CloseClick(object sender, EventArgs e) + { + Close(); + } + private void RunAsync(string status, Action work) { SetBusy(true, status); @@ -342,6 +375,7 @@ namespace BizTalkPlatformManagementTool.Ui { _statusGrid.Rows.Add("HostInstance", string.Empty, item.InstanceName, item.StateText, item.HostName + " on " + item.Server); } + UpdateEnvironmentStatus(snapshot); }); } @@ -405,6 +439,8 @@ namespace BizTalkPlatformManagementTool.Ui _compareButton.Enabled = !busy; _shutdownButton.Enabled = !busy; _restoreButton.Enabled = !busy; + _clearButton.Enabled = !busy; + _closeButton.Enabled = !busy; _statusLabel.Text = status; }); } @@ -440,16 +476,56 @@ namespace BizTalkPlatformManagementTool.Ui private static Label Label(string text) { - return new Label { Text = text, Dock = DockStyle.Fill, TextAlign = ContentAlignment.MiddleLeft }; + return new Label { Text = text, Dock = DockStyle.Fill, TextAlign = ContentAlignment.MiddleRight, Margin = new Padding(0, 5, 4, 5) }; } private static Button ActionButton(string text, EventHandler handler) { - var button = new Button { Text = text, Width = 148, Height = 34, Margin = new Padding(0, 0, 8, 0) }; + var button = new Button { Text = text, Width = 112, Height = 34, Margin = new Padding(0, 0, 8, 0) }; button.Click += handler; return button; } + private static void ConfigureInput(Control control) + { + control.Dock = DockStyle.Fill; + control.Margin = new Padding(4, 6, 8, 6); + } + + private void UpdateEnvironmentStatus(BizTalkSnapshot snapshot) + { + if (snapshot == null || snapshot.HostInstances == null || snapshot.HostInstances.Count == 0) + { + _environmentStatusLabel.Text = "Environment: Unknown"; + _environmentStatusLabel.BackColor = SystemColors.Control; + _environmentStatusLabel.ForeColor = SystemColors.ControlText; + return; + } + + var total = snapshot.HostInstances.Count; + var started = snapshot.HostInstances.Count(x => x.RawState == ArtifactStates.HostStarted); + var pending = snapshot.HostInstances.Count(x => x.RawState == ArtifactStates.HostStartPending || x.RawState == ArtifactStates.HostStopPending); + + if (started == total) + { + _environmentStatusLabel.Text = "Environment: Started (" + started + "/" + total + ")"; + _environmentStatusLabel.BackColor = Color.FromArgb(230, 245, 233); + _environmentStatusLabel.ForeColor = Color.DarkGreen; + } + else if (started == 0 && pending == 0) + { + _environmentStatusLabel.Text = "Environment: Stopped (0/" + total + ")"; + _environmentStatusLabel.BackColor = Color.FromArgb(252, 232, 230); + _environmentStatusLabel.ForeColor = Color.DarkRed; + } + else + { + _environmentStatusLabel.Text = "Environment: Partial (" + started + "/" + total + ")"; + _environmentStatusLabel.BackColor = Color.FromArgb(255, 244, 214); + _environmentStatusLabel.ForeColor = Color.DarkOrange; + } + } + private static void ConfigureGrid(DataGridView grid) { grid.Dock = DockStyle.Fill;