Fixed some UI layout stuff.

This commit is contained in:
2026-06-01 15:26:47 +02:00
parent 076504753e
commit 27299fc8e7
3 changed files with 105 additions and 22 deletions
+3
View File
@@ -35,6 +35,8 @@ Das BizTalk Platform Management Tool unterstützt kontrollierte Wartungsfenster
8. Nach der Wartung mit **Restore** aus `before.json` wiederherstellen. 8. Nach der Wartung mit **Restore** aus `before.json` wiederherstellen.
9. Mit **Snapshot After** und **Compare** die Umgebung validieren. 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 ## Sicherheitsdesign
- Dry-run ist standardmäßig aktiviert. - 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. - 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. - 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. - 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. - Operationspläne werden vor Laufzeitänderungen gespeichert.
- WMI-Methodenrückgaben werden geprüft. - WMI-Methodenrückgaben werden geprüft.
- Wartezeiten nutzen konfigurierbare Timeout- und Polling-Werte. - Wartezeiten nutzen konfigurierbare Timeout- und Polling-Werte.
+4
View File
@@ -21,6 +21,8 @@ WinForms tool for controlled Microsoft BizTalk Server 2020 platform operations d
- Dry-run mode enabled by default - Dry-run mode enabled by default
- WMI access through `root\MicrosoftBizTalkServer` - WMI access through `root\MicrosoftBizTalkServer`
- Detailed operation logging in the GUI and daily rolling log files next to the executable - 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 - No compile-time dependency on BizTalk ExplorerOM assemblies
## Safe Usage ## 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`. 7. After maintenance, click **Restore** using the saved `before.json`.
8. Click **Snapshot After** and **Compare**. 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 ## Operation Order
Shutdown: Shutdown:
@@ -1,6 +1,7 @@
using System; using System;
using System.Drawing; using System.Drawing;
using System.IO; using System.IO;
using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using System.Windows.Forms; using System.Windows.Forms;
using BizTalkPlatformManagementTool.Models; using BizTalkPlatformManagementTool.Models;
@@ -20,6 +21,7 @@ namespace BizTalkPlatformManagementTool.Ui
private readonly DataGridView _logGrid = new DataGridView(); private readonly DataGridView _logGrid = new DataGridView();
private readonly StatusStrip _statusStrip = new StatusStrip(); private readonly StatusStrip _statusStrip = new StatusStrip();
private readonly ToolStripStatusLabel _statusLabel = new ToolStripStatusLabel(); private readonly ToolStripStatusLabel _statusLabel = new ToolStripStatusLabel();
private readonly Label _environmentStatusLabel = new Label();
private readonly OperationLogger _logger; private readonly OperationLogger _logger;
private readonly BizTalkOperationService _service; private readonly BizTalkOperationService _service;
@@ -29,6 +31,8 @@ namespace BizTalkPlatformManagementTool.Ui
private Button _compareButton; private Button _compareButton;
private Button _shutdownButton; private Button _shutdownButton;
private Button _restoreButton; private Button _restoreButton;
private Button _clearButton;
private Button _closeButton;
public MainForm() public MainForm()
{ {
@@ -53,7 +57,7 @@ namespace BizTalkPlatformManagementTool.Ui
RowCount = 4, RowCount = 4,
Padding = new Padding(10) 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.Absolute, 54));
root.RowStyles.Add(new RowStyle(SizeType.Percent, 100)); root.RowStyles.Add(new RowStyle(SizeType.Percent, 100));
root.RowStyles.Add(new RowStyle(SizeType.Absolute, 24)); root.RowStyles.Add(new RowStyle(SizeType.Absolute, 24));
@@ -70,42 +74,52 @@ namespace BizTalkPlatformManagementTool.Ui
private Control BuildSettingsPanel() private Control BuildSettingsPanel()
{ {
var panel = new TableLayoutPanel { Dock = DockStyle.Fill, ColumnCount = 8, RowCount = 2 }; var panel = new TableLayoutPanel { Dock = DockStyle.Fill, ColumnCount = 10, RowCount = 2 };
panel.ColumnStyles.Add(new ColumnStyle(SizeType.Absolute, 70)); panel.ColumnStyles.Add(new ColumnStyle(SizeType.Absolute, 64));
panel.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 30)); 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.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, 72));
panel.ColumnStyles.Add(new ColumnStyle(SizeType.Absolute, 88)); panel.ColumnStyles.Add(new ColumnStyle(SizeType.Absolute, 76));
panel.RowStyles.Add(new RowStyle(SizeType.Absolute, 36)); panel.ColumnStyles.Add(new ColumnStyle(SizeType.Absolute, 220));
panel.RowStyles.Add(new RowStyle(SizeType.Absolute, 36)); panel.RowStyles.Add(new RowStyle(SizeType.Absolute, 40));
panel.RowStyles.Add(new RowStyle(SizeType.Absolute, 40));
_serverTextBox.Text = Environment.MachineName; _serverTextBox.Text = Environment.MachineName;
_serverTextBox.Dock = DockStyle.Fill; ConfigureInput(_serverTextBox);
_outputTextBox.Text = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory), "BizTalkPlatformManagementTool"); _outputTextBox.Text = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory), "BizTalkPlatformManagementTool");
_outputTextBox.Dock = DockStyle.Fill; ConfigureInput(_outputTextBox);
_stateFileTextBox.Text = "before.json"; _stateFileTextBox.Text = "before.json";
_stateFileTextBox.Dock = DockStyle.Fill; ConfigureInput(_stateFileTextBox);
_timeoutInput.Minimum = 30; _timeoutInput.Minimum = 30;
_timeoutInput.Maximum = 3600; _timeoutInput.Maximum = 3600;
_timeoutInput.Value = 300; _timeoutInput.Value = 300;
_timeoutInput.Dock = DockStyle.Fill; ConfigureInput(_timeoutInput);
_pollInput.Minimum = 1; _pollInput.Minimum = 1;
_pollInput.Maximum = 60; _pollInput.Maximum = 60;
_pollInput.Value = 5; _pollInput.Value = 5;
_pollInput.Dock = DockStyle.Fill; ConfigureInput(_pollInput);
_dryRunCheckBox.Text = "Dry run"; _dryRunCheckBox.Text = "Dry run";
_dryRunCheckBox.Checked = true; _dryRunCheckBox.Checked = true;
_dryRunCheckBox.Dock = DockStyle.Fill; _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; 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(Label("Server"), 0, 0);
panel.Controls.Add(_serverTextBox, 1, 0); panel.Controls.Add(_serverTextBox, 1, 0);
panel.Controls.Add(Label("Output"), 2, 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(Label("State"), 0, 1);
panel.Controls.Add(_stateFileTextBox, 1, 1); panel.Controls.Add(_stateFileTextBox, 1, 1);
panel.SetColumnSpan(_stateFileTextBox, 3); panel.SetColumnSpan(_stateFileTextBox, 2);
panel.Controls.Add(_dryRunCheckBox, 4, 1); panel.Controls.Add(_dryRunCheckBox, 3, 1);
panel.Controls.Add(Label("Poll sec."), 5, 1); panel.Controls.Add(Label("Poll sec."), 7, 1);
panel.Controls.Add(_pollInput, 6, 1); panel.Controls.Add(_pollInput, 8, 1);
panel.Controls.Add(_environmentStatusLabel, 9, 0);
panel.SetRowSpan(_environmentStatusLabel, 2);
return panel; return panel;
} }
private Control BuildActionPanel() 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); _diagnoseButton = ActionButton("Diagnose", DiagnoseClick);
_beforeButton = ActionButton("Snapshot Before", BeforeClick); _beforeButton = ActionButton("Snapshot Before", BeforeClick);
_afterButton = ActionButton("Snapshot After", AfterClick); _afterButton = ActionButton("Snapshot After", AfterClick);
_compareButton = ActionButton("Compare", CompareClick); _compareButton = ActionButton("Compare", CompareClick);
_shutdownButton = ActionButton("Shutdown", ShutdownClick); _shutdownButton = ActionButton("Shutdown", ShutdownClick);
_restoreButton = ActionButton("Restore", RestoreClick); _restoreButton = ActionButton("Restore", RestoreClick);
_clearButton = ActionButton("Clear", ClearClick);
_closeButton = ActionButton("Close", CloseClick);
panel.Controls.Add(_diagnoseButton); panel.Controls.Add(_diagnoseButton);
panel.Controls.Add(_beforeButton); panel.Controls.Add(_beforeButton);
@@ -140,6 +158,8 @@ namespace BizTalkPlatformManagementTool.Ui
panel.Controls.Add(_compareButton); panel.Controls.Add(_compareButton);
panel.Controls.Add(_shutdownButton); panel.Controls.Add(_shutdownButton);
panel.Controls.Add(_restoreButton); panel.Controls.Add(_restoreButton);
panel.Controls.Add(_clearButton);
panel.Controls.Add(_closeButton);
return panel; 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) private void RunAsync(string status, Action work)
{ {
SetBusy(true, status); 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); _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; _compareButton.Enabled = !busy;
_shutdownButton.Enabled = !busy; _shutdownButton.Enabled = !busy;
_restoreButton.Enabled = !busy; _restoreButton.Enabled = !busy;
_clearButton.Enabled = !busy;
_closeButton.Enabled = !busy;
_statusLabel.Text = status; _statusLabel.Text = status;
}); });
} }
@@ -440,16 +476,56 @@ namespace BizTalkPlatformManagementTool.Ui
private static Label Label(string text) 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) 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; button.Click += handler;
return button; 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) private static void ConfigureGrid(DataGridView grid)
{ {
grid.Dock = DockStyle.Fill; grid.Dock = DockStyle.Fill;