diff --git a/ZA.CoreService.ESBCertificateManager/Form1.cs b/ZA.CoreService.ESBCertificateManager/Form1.cs
index 4a96ce5..a588088 100644
--- a/ZA.CoreService.ESBCertificateManager/Form1.cs
+++ b/ZA.CoreService.ESBCertificateManager/Form1.cs
@@ -172,13 +172,12 @@ namespace ZA.CoreService.ESBCertificateManager
coordinator,
isSettingsMode: true);
- if (settingsForm.ShowDialog(this) != DialogResult.OK)
- {
- return;
- }
+ // Nach dem Schließen immer neu laden:
+ // Pfade/Container können auch ohne „Profil übernehmen“ angelegt worden sein.
+ _ = settingsForm.ShowDialog(this);
SetStatus(
- "Einstellungen übernommen. Anwendung wird aktualisiert ...",
+ "Einstellungen geschlossen. Ziele werden aktualisiert ...",
isError: false);
await InitializeApplicationAsync();
@@ -1938,6 +1937,24 @@ namespace ZA.CoreService.ESBCertificateManager
{
UpdateToNextStep(4);
}
+ else
+ {
+ string details = string.Join(
+ Environment.NewLine + Environment.NewLine,
+ runResult.TargetResults
+ .Where(result => !result.Success)
+ .Select(result =>
+ $"{result.TargetName}: {result.StatusText}"
+ + Environment.NewLine
+ + (result.Detail ?? string.Empty)));
+
+ CopyableErrorDialog.Show(
+ this,
+ "Neustart fehlgeschlagen (MfApi)",
+ string.IsNullOrWhiteSpace(details)
+ ? "Neustart fehlgeschlagen (keine Details)."
+ : details);
+ }
}
catch (OperationCanceledException)
{
@@ -1946,7 +1963,10 @@ namespace ZA.CoreService.ESBCertificateManager
catch (Exception ex)
{
SetStatus($"Neustart fehlgeschlagen: {ex.Message}", isError: true);
- MessageBox.Show(this, ex.Message, "ESB neu starten", MessageBoxButtons.OK, MessageBoxIcon.Error);
+ CopyableErrorDialog.Show(
+ this,
+ "Neustart fehlgeschlagen (MfApi)",
+ ex.ToString());
}
finally
{
@@ -2051,6 +2071,20 @@ namespace ZA.CoreService.ESBCertificateManager
SetStatus(
"Deployment für mindestens ein Ziel fehlgeschlagen.",
isError: true);
+
+ string details = string.Join(
+ Environment.NewLine + Environment.NewLine,
+ runResult.TargetResults
+ .Where(result => !result.Success)
+ .Select(result =>
+ $"{result.TargetName}: {result.StatusText}"
+ + Environment.NewLine
+ + (result.Detail ?? string.Empty)));
+
+ CopyableErrorDialog.Show(
+ this,
+ "Deployment fehlgeschlagen",
+ details);
}
}
catch (OperationCanceledException)
@@ -2063,12 +2097,10 @@ namespace ZA.CoreService.ESBCertificateManager
$"Deployment fehlgeschlagen: {ex.Message}",
isError: true);
- MessageBox.Show(
+ CopyableErrorDialog.Show(
this,
- ex.Message,
"Deployment fehlgeschlagen",
- MessageBoxButtons.OK,
- MessageBoxIcon.Error);
+ ex.ToString());
}
finally
{
diff --git a/ZA.CoreService.ESBCertificateManager/Models/AppSettings.cs b/ZA.CoreService.ESBCertificateManager/Models/AppSettings.cs
index 416ab06..97ae614 100644
--- a/ZA.CoreService.ESBCertificateManager/Models/AppSettings.cs
+++ b/ZA.CoreService.ESBCertificateManager/Models/AppSettings.cs
@@ -46,7 +46,7 @@ public sealed class DatabaseSettings
public sealed class RuntimeSettings
{
public string JavaExecutablePath { get; set; } =
- @"Runtime\bin\java.exe";
+ @"C:\Program Files (x86)\Java\jre1.8.0_481\bin\java.exe";
public string SonicClientLibraryPath { get; set; } =
@"Runtime\SonicClient\lib";
diff --git a/ZA.CoreService.ESBCertificateManager/Models/DatabaseSonicConnection.cs b/ZA.CoreService.ESBCertificateManager/Models/DatabaseSonicConnection.cs
index b7fdbd8..1482a8e 100644
--- a/ZA.CoreService.ESBCertificateManager/Models/DatabaseSonicConnection.cs
+++ b/ZA.CoreService.ESBCertificateManager/Models/DatabaseSonicConnection.cs
@@ -72,10 +72,18 @@ public sealed class DatabaseSonicConnection
"Bitte die Einstellungen öffnen und ein Benutzerprofil hinterlegen.");
}
- string javaExecutablePath =
- PathResolver.ResolvePath(
+ string? javaExecutablePath =
+ JavaRuntimeLocator.Resolve(
runtimeSettings.JavaExecutablePath);
+ if (javaExecutablePath is null)
+ {
+ throw new InvalidOperationException(
+ "Java 8 wurde nicht gefunden. " +
+ "Bitte Runtime:JavaExecutablePath auf " +
+ @"jre1.8*\bin\java.exe setzen.");
+ }
+
string sonicClientLibraryPath =
PathResolver.ResolvePath(
runtimeSettings.SonicClientLibraryPath);
diff --git a/ZA.CoreService.ESBCertificateManager/Services/CopyableErrorDialog.cs b/ZA.CoreService.ESBCertificateManager/Services/CopyableErrorDialog.cs
new file mode 100644
index 0000000..6227fd3
--- /dev/null
+++ b/ZA.CoreService.ESBCertificateManager/Services/CopyableErrorDialog.cs
@@ -0,0 +1,135 @@
+namespace ZA.CoreService.ESBCertificateManager.Services;
+
+///
+/// Fehlerdialog mit Text und Button „In Zwischenablage kopieren“.
+/// Kopiert den Fehlertext beim Öffnen automatisch.
+///
+public static class CopyableErrorDialog
+{
+ public static void Show(
+ IWin32Window? owner,
+ string title,
+ string details)
+ {
+ string text = string.IsNullOrWhiteSpace(details)
+ ? "(keine Fehlerdetails)"
+ : details.Trim();
+
+ TryCopy(text);
+
+ using Form dialog = new()
+ {
+ Text = title,
+ StartPosition = FormStartPosition.CenterParent,
+ FormBorderStyle = FormBorderStyle.FixedDialog,
+ MaximizeBox = false,
+ MinimizeBox = false,
+ ShowInTaskbar = false,
+ ClientSize = new Size(640, 420),
+ BackColor = Color.FromArgb(16, 28, 48),
+ ForeColor = Color.FromArgb(241, 245, 249),
+ Font = new Font("Segoe UI", 9.5f)
+ };
+
+ Label hint = new()
+ {
+ Text =
+ "Fehlertext ist in der Zwischenablage — "
+ + "einfach hier einfügen (Strg+V).",
+ Location = new Point(16, 12),
+ AutoSize = false,
+ Size = new Size(608, 28),
+ ForeColor = Color.FromArgb(208, 171, 57)
+ };
+
+ TextBox box = new()
+ {
+ Location = new Point(16, 44),
+ Size = new Size(608, 310),
+ Multiline = true,
+ ReadOnly = true,
+ ScrollBars = ScrollBars.Both,
+ WordWrap = false,
+ Text = text,
+ BackColor = Color.FromArgb(12, 22, 38),
+ ForeColor = Color.FromArgb(241, 245, 249),
+ BorderStyle = BorderStyle.FixedSingle,
+ Font = new Font("Consolas", 9f)
+ };
+
+ Label copyStatus = new()
+ {
+ Text = "✓ In Zwischenablage kopiert",
+ Location = new Point(16, 368),
+ AutoSize = true,
+ ForeColor = Color.FromArgb(90, 200, 140)
+ };
+
+ Button btnCopy = new()
+ {
+ Text = "Nochmal kopieren",
+ Location = new Point(280, 362),
+ Size = new Size(160, 36),
+ FlatStyle = FlatStyle.Flat,
+ BackColor = Color.FromArgb(39, 52, 73),
+ ForeColor = Color.FromArgb(241, 245, 249),
+ Cursor = Cursors.Hand
+ };
+
+ btnCopy.FlatAppearance.BorderColor =
+ Color.FromArgb(36, 74, 117);
+
+ btnCopy.Click += (_, _) =>
+ {
+ if (TryCopy(text))
+ {
+ copyStatus.Text = "✓ Erneut kopiert";
+ copyStatus.ForeColor =
+ Color.FromArgb(90, 200, 140);
+ }
+ else
+ {
+ copyStatus.Text = "Kopieren fehlgeschlagen";
+ copyStatus.ForeColor =
+ Color.FromArgb(220, 100, 100);
+ }
+ };
+
+ Button btnClose = new()
+ {
+ Text = "Schließen",
+ Location = new Point(456, 362),
+ Size = new Size(168, 36),
+ FlatStyle = FlatStyle.Flat,
+ BackColor = Color.FromArgb(0, 110, 182),
+ ForeColor = Color.White,
+ Cursor = Cursors.Hand,
+ DialogResult = DialogResult.OK
+ };
+
+ btnClose.FlatAppearance.BorderSize = 0;
+
+ dialog.Controls.Add(hint);
+ dialog.Controls.Add(box);
+ dialog.Controls.Add(copyStatus);
+ dialog.Controls.Add(btnCopy);
+ dialog.Controls.Add(btnClose);
+ dialog.AcceptButton = btnClose;
+ dialog.CancelButton = btnClose;
+
+ dialog.ShowDialog(owner);
+ }
+
+ private static bool TryCopy(string text)
+ {
+ try
+ {
+ Clipboard.SetText(text);
+ return true;
+ }
+ catch
+ {
+ return false;
+ }
+ }
+}
diff --git a/ZA.CoreService.ESBCertificateManager/Services/JavaRuntimeLocator.cs b/ZA.CoreService.ESBCertificateManager/Services/JavaRuntimeLocator.cs
new file mode 100644
index 0000000..1352b63
--- /dev/null
+++ b/ZA.CoreService.ESBCertificateManager/Services/JavaRuntimeLocator.cs
@@ -0,0 +1,121 @@
+namespace ZA.CoreService.ESBCertificateManager.Services;
+
+///
+/// Findet eine nutzbare Java-8-Runtime für Sonic MfApi.
+///
+public static class JavaRuntimeLocator
+{
+ public static string? Resolve(
+ string? configuredPath = null)
+ {
+ foreach (string? candidate in EnumerateCandidates(configuredPath))
+ {
+ if (string.IsNullOrWhiteSpace(candidate))
+ {
+ continue;
+ }
+
+ string? resolved = TryResolveExisting(candidate);
+
+ if (resolved is not null)
+ {
+ return resolved;
+ }
+ }
+
+ return null;
+ }
+
+ private static IEnumerable EnumerateCandidates(
+ string? configuredPath)
+ {
+ if (!string.IsNullOrWhiteSpace(configuredPath))
+ {
+ yield return configuredPath.Trim();
+ }
+
+ yield return
+ @"C:\Program Files (x86)\Java\jre1.8.0_481\bin\java.exe";
+
+ yield return
+ @"C:\Program Files (x86)\Java\jre1.8.0_501\bin\java.exe";
+
+ yield return
+ @"C:\Program Files\Java\jre1.8.0_481\bin\java.exe";
+
+ yield return
+ @"C:\Program Files (x86)\Common Files\Oracle\Java\java8path\java.exe";
+
+ foreach (string root in new[]
+ {
+ @"C:\Program Files (x86)\Java",
+ @"C:\Program Files\Java"
+ })
+ {
+ if (!Directory.Exists(root))
+ {
+ continue;
+ }
+
+ foreach (string directory in Directory
+ .EnumerateDirectories(root, "jre1.8*")
+ .OrderByDescending(path => path, StringComparer.OrdinalIgnoreCase))
+ {
+ yield return Path.Combine(directory, "bin", "java.exe");
+ }
+
+ foreach (string directory in Directory
+ .EnumerateDirectories(root, "jdk1.8*")
+ .OrderByDescending(path => path, StringComparer.OrdinalIgnoreCase))
+ {
+ yield return Path.Combine(directory, "bin", "java.exe");
+ }
+ }
+
+ string? javaHome =
+ Environment.GetEnvironmentVariable("JAVA_HOME");
+
+ if (!string.IsNullOrWhiteSpace(javaHome))
+ {
+ yield return Path.Combine(
+ javaHome.Trim(),
+ "bin",
+ "java.exe");
+ }
+
+ string? jreHome =
+ Environment.GetEnvironmentVariable("JRE_HOME");
+
+ if (!string.IsNullOrWhiteSpace(jreHome))
+ {
+ yield return Path.Combine(
+ jreHome.Trim(),
+ "bin",
+ "java.exe");
+ }
+
+ yield return "java.exe";
+ }
+
+ private static string? TryResolveExisting(string candidate)
+ {
+ try
+ {
+ string resolved =
+ Path.IsPathRooted(candidate)
+ ? Path.GetFullPath(candidate)
+ : Path.GetFullPath(
+ Path.Combine(
+ AppContext.BaseDirectory,
+ candidate));
+
+ return File.Exists(resolved)
+ ? resolved
+ : null;
+ }
+ catch
+ {
+ return null;
+ }
+ }
+}
diff --git a/ZA.CoreService.ESBCertificateManager/Services/RestartExecutor.cs b/ZA.CoreService.ESBCertificateManager/Services/RestartExecutor.cs
index 41e9297..00b0896 100644
--- a/ZA.CoreService.ESBCertificateManager/Services/RestartExecutor.cs
+++ b/ZA.CoreService.ESBCertificateManager/Services/RestartExecutor.cs
@@ -27,7 +27,9 @@ public sealed class RestartExecutor
if (connection is null)
{
return (false, "Sonic-Verbindung nicht gefunden",
- $"Ziel '{target.Name}': SonicConnection '{target.SonicConnectionName}' fehlt in appsettings.");
+ $"Ziel '{target.Name}': SonicConnection '{target.SonicConnectionName}' "
+ + "ist nicht geladen. Meist fehlt ein Benutzerprofil "
+ + "(Einstellungen → Profil anlegen und übernehmen).");
}
using SonicManagementClient client =
diff --git a/ZA.CoreService.ESBCertificateManager/Services/RuntimeEnviromentValidator.cs b/ZA.CoreService.ESBCertificateManager/Services/RuntimeEnviromentValidator.cs
index 767d781..a65c355 100644
--- a/ZA.CoreService.ESBCertificateManager/Services/RuntimeEnviromentValidator.cs
+++ b/ZA.CoreService.ESBCertificateManager/Services/RuntimeEnviromentValidator.cs
@@ -11,8 +11,8 @@ public sealed class RuntimeEnvironmentValidator
{
List issues = [];
- string javaExecutablePath =
- PathResolver.ResolvePath(
+ string? javaExecutablePath =
+ JavaRuntimeLocator.Resolve(
settings.JavaExecutablePath);
string sonicClientLibraryPath =
@@ -21,10 +21,11 @@ public sealed class RuntimeEnvironmentValidator
string javaVersion = string.Empty;
- if (!File.Exists(javaExecutablePath))
+ if (javaExecutablePath is null)
{
issues.Add(
- $"Java wurde nicht gefunden: {javaExecutablePath}");
+ "Java 8 wurde nicht gefunden. "
+ + "Runtime:JavaExecutablePath oder installierte jre1.8* prüfen.");
}
else
{
@@ -80,7 +81,7 @@ public sealed class RuntimeEnvironmentValidator
return new RuntimeValidationResult
{
IsValid = issues.Count == 0,
- JavaExecutablePath = javaExecutablePath,
+ JavaExecutablePath = javaExecutablePath ?? string.Empty,
SonicClientLibraryPath = sonicClientLibraryPath,
JavaVersion = javaVersion,
Issues = issues
diff --git a/ZA.CoreService.ESBCertificateManager/Services/SonicCredentialTester.cs b/ZA.CoreService.ESBCertificateManager/Services/SonicCredentialTester.cs
index 7b5606d..583fca4 100644
--- a/ZA.CoreService.ESBCertificateManager/Services/SonicCredentialTester.cs
+++ b/ZA.CoreService.ESBCertificateManager/Services/SonicCredentialTester.cs
@@ -44,8 +44,8 @@ public sealed class SonicCredentialTester
"Für den Verbindungstest fehlt ein Container.");
}
- string javaPath =
- PathResolver.ResolvePath(
+ string? javaPath =
+ JavaRuntimeLocator.Resolve(
_runtimeSettings.JavaExecutablePath);
string libraryPath =
@@ -55,10 +55,12 @@ public sealed class SonicCredentialTester
string? toolsPath =
ResolveToolsDirectory();
- if (!File.Exists(javaPath))
+ if (javaPath is null)
{
return CredentialTestResult.Failed(
- $"Java wurde nicht gefunden: {javaPath}");
+ "Java 8 wurde nicht gefunden. "
+ + "Runtime:JavaExecutablePath prüfen "
+ + @"(z. B. C:\Program Files (x86)\Java\jre1.8.0_481\bin\java.exe).");
}
if (!Directory.Exists(libraryPath))
diff --git a/ZA.CoreService.ESBCertificateManager/Services/SonicMfApiExecutor.cs b/ZA.CoreService.ESBCertificateManager/Services/SonicMfApiExecutor.cs
index 2fa318a..d445da6 100644
--- a/ZA.CoreService.ESBCertificateManager/Services/SonicMfApiExecutor.cs
+++ b/ZA.CoreService.ESBCertificateManager/Services/SonicMfApiExecutor.cs
@@ -356,84 +356,35 @@ public sealed class SonicMfApiExecutor
private string? ResolveJavaExe()
{
- foreach (string? candidate
- in EnumerateJavaCandidates())
+ // Explizite Verbindungs-Pfade zuerst, dann Java-8-Suche
+ // (Runtime\bin\java.exe fehlt oft; JAVA_HOME zeigt oft auf JDK 21).
+ string? fromConnection = JavaRuntimeLocator.Resolve(
+ !string.IsNullOrWhiteSpace(_connection.JavaPath)
+ ? _connection.JavaPath
+ : null);
+
+ if (fromConnection is not null)
{
- if (string.IsNullOrWhiteSpace(candidate))
- {
- continue;
- }
-
- string resolvedCandidate;
-
- try
- {
- resolvedCandidate =
- Path.IsPathRooted(candidate)
- ? Path.GetFullPath(candidate)
- : Path.GetFullPath(
- Path.Combine(
- AppContext.BaseDirectory,
- candidate));
- }
- catch
- {
- continue;
- }
-
- if (File.Exists(resolvedCandidate))
- {
- return resolvedCandidate;
- }
+ return fromConnection;
}
- return null;
- }
-
- private IEnumerable
- EnumerateJavaCandidates()
- {
- if (!string.IsNullOrWhiteSpace(
- _connection.JavaPath))
+ if (!string.IsNullOrWhiteSpace(_connection.JavaHome))
{
- yield return
- _connection.JavaPath.Trim();
- }
-
- if (!string.IsNullOrWhiteSpace(
- _connection.JavaHome))
- {
- yield return Path.Combine(
+ string fromHome = Path.Combine(
_connection.JavaHome.Trim(),
"bin",
"java.exe");
+
+ string? resolvedHome =
+ JavaRuntimeLocator.Resolve(fromHome);
+
+ if (resolvedHome is not null)
+ {
+ return resolvedHome;
+ }
}
- string? javaHome =
- Environment.GetEnvironmentVariable(
- "JAVA_HOME");
-
- if (!string.IsNullOrWhiteSpace(javaHome))
- {
- yield return Path.Combine(
- javaHome.Trim(),
- "bin",
- "java.exe");
- }
-
- string? jreHome =
- Environment.GetEnvironmentVariable(
- "JRE_HOME");
-
- if (!string.IsNullOrWhiteSpace(jreHome))
- {
- yield return Path.Combine(
- jreHome.Trim(),
- "bin",
- "java.exe");
- }
-
- yield return "java.exe";
+ return JavaRuntimeLocator.Resolve();
}
private (
diff --git a/ZA.CoreService.ESBCertificateManager/Setup/SetupWizardForm.cs b/ZA.CoreService.ESBCertificateManager/Setup/SetupWizardForm.cs
index ccc3aa1..4fdff3a 100644
--- a/ZA.CoreService.ESBCertificateManager/Setup/SetupWizardForm.cs
+++ b/ZA.CoreService.ESBCertificateManager/Setup/SetupWizardForm.cs
@@ -67,6 +67,15 @@ public sealed class SetupWizardForm : Form
ShowPanel(_panelStatus, _navButtons[0]);
Shown += async (_, _) => await RefreshAllAsync();
+
+ FormClosing += (_, e) =>
+ {
+ // X-Button: in Einstellungen trotzdem als „geschlossen mit Änderungen möglich“
+ if (_isSettingsMode && DialogResult == DialogResult.None)
+ {
+ DialogResult = DialogResult.OK;
+ }
+ };
}
private void BuildShell()
@@ -1138,10 +1147,10 @@ public sealed class SetupWizardForm : Form
{
if (_isSettingsMode)
{
- SetupCheckResult check = await _coordinator.CheckAsync();
- DialogResult = check.IsReady
- ? DialogResult.OK
- : DialogResult.Cancel;
+ // Katalog-Änderungen (Pfade/Container) sollen die Hauptansicht
+ // immer aktualisieren – unabhängig davon, ob das Profil schon „ready“ ist.
+ _ = await _coordinator.CheckAsync();
+ DialogResult = DialogResult.OK;
}
else
{
diff --git a/ZA.CoreService.ESBCertificateManager/Tools/SonicMfContainerTool$Args.class b/ZA.CoreService.ESBCertificateManager/Tools/SonicMfContainerTool$Args.class
index 729a334..b205b3a 100644
Binary files a/ZA.CoreService.ESBCertificateManager/Tools/SonicMfContainerTool$Args.class and b/ZA.CoreService.ESBCertificateManager/Tools/SonicMfContainerTool$Args.class differ
diff --git a/ZA.CoreService.ESBCertificateManager/Tools/SonicMfContainerTool.class b/ZA.CoreService.ESBCertificateManager/Tools/SonicMfContainerTool.class
index 59a4fa6..5e969e7 100644
Binary files a/ZA.CoreService.ESBCertificateManager/Tools/SonicMfContainerTool.class and b/ZA.CoreService.ESBCertificateManager/Tools/SonicMfContainerTool.class differ
diff --git a/ZA.CoreService.ESBCertificateManager/Tools/SonicMfContainerTool.jar b/ZA.CoreService.ESBCertificateManager/Tools/SonicMfContainerTool.jar
index e944331..86beb9f 100644
Binary files a/ZA.CoreService.ESBCertificateManager/Tools/SonicMfContainerTool.jar and b/ZA.CoreService.ESBCertificateManager/Tools/SonicMfContainerTool.jar differ
diff --git a/ZA.CoreService.ESBCertificateManager/appsettings.json b/ZA.CoreService.ESBCertificateManager/appsettings.json
index ea9755d..ae23177 100644
--- a/ZA.CoreService.ESBCertificateManager/appsettings.json
+++ b/ZA.CoreService.ESBCertificateManager/appsettings.json
@@ -6,7 +6,7 @@
"ConnectionString": "Server=VWEBDEV01;Database=EsbZertifikatManager;Integrated Security=True;Encrypt=True;Column Encryption Setting=Enabled;Application Name=ZA.CoreService.ESBCertificateManager;TrustServerCertificate=True;"
},
"Runtime": {
- "JavaExecutablePath": "Runtime\\bin\\java.exe",
+ "JavaExecutablePath": "C:\\Program Files (x86)\\Java\\jre1.8.0_481\\bin\\java.exe",
"SonicClientLibraryPath": "Runtime\\SonicClient\\lib",
"SetupCompleted": true
},