Fix Java 8 resolution for MfApi restart, refresh targets after settings, and copy errors to clipboard.
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -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
|
||||
{
|
||||
|
||||
@@ -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";
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -0,0 +1,135 @@
|
||||
namespace ZA.CoreService.ESBCertificateManager.Services;
|
||||
|
||||
/// <summary>
|
||||
/// Fehlerdialog mit Text und Button „In Zwischenablage kopieren“.
|
||||
/// Kopiert den Fehlertext beim Öffnen automatisch.
|
||||
/// </summary>
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,121 @@
|
||||
namespace ZA.CoreService.ESBCertificateManager.Services;
|
||||
|
||||
/// <summary>
|
||||
/// Findet eine nutzbare Java-8-Runtime für Sonic MfApi.
|
||||
/// </summary>
|
||||
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<string?> 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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 =
|
||||
|
||||
@@ -11,8 +11,8 @@ public sealed class RuntimeEnvironmentValidator
|
||||
{
|
||||
List<string> 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
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -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;
|
||||
return fromConnection;
|
||||
}
|
||||
|
||||
string resolvedCandidate;
|
||||
|
||||
try
|
||||
if (!string.IsNullOrWhiteSpace(_connection.JavaHome))
|
||||
{
|
||||
resolvedCandidate =
|
||||
Path.IsPathRooted(candidate)
|
||||
? Path.GetFullPath(candidate)
|
||||
: Path.GetFullPath(
|
||||
Path.Combine(
|
||||
AppContext.BaseDirectory,
|
||||
candidate));
|
||||
}
|
||||
catch
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (File.Exists(resolvedCandidate))
|
||||
{
|
||||
return resolvedCandidate;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private IEnumerable<string?>
|
||||
EnumerateJavaCandidates()
|
||||
{
|
||||
if (!string.IsNullOrWhiteSpace(
|
||||
_connection.JavaPath))
|
||||
{
|
||||
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? javaHome =
|
||||
Environment.GetEnvironmentVariable(
|
||||
"JAVA_HOME");
|
||||
string? resolvedHome =
|
||||
JavaRuntimeLocator.Resolve(fromHome);
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(javaHome))
|
||||
if (resolvedHome is not null)
|
||||
{
|
||||
yield return Path.Combine(
|
||||
javaHome.Trim(),
|
||||
"bin",
|
||||
"java.exe");
|
||||
return resolvedHome;
|
||||
}
|
||||
}
|
||||
|
||||
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 (
|
||||
|
||||
@@ -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
|
||||
{
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -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
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user