using System; using System.Drawing; using System.Windows.Forms; using LicenseLabrador.Client; using PolyTraderSharp.Licensing; namespace PolyTraderSharp.Ui { /// /// Modaler Lizenzdialog beim Programmstart, wenn keine gültige Lizenz vorliegt. Zeigt die /// Hardware-ID (kopierbar, für die Aktivierung im Lizenz-Admin), nimmt einen Lizenzschlüssel /// entgegen und validiert ihn gegen den Lizenzserver. Bei Erfolg werden /// und gesetzt; der Aufrufer (LicenseGate) speichert den Schlüssel. /// Ohne gültige Lizenz kann der Nutzer eingeschränkt (nur Core-Shell) weiterstarten. /// public partial class LicenseDialog : Form { private readonly LicenseClient _client; /// Nur gesetzt, wenn im Dialog erfolgreich validiert wurde. public LicenseResult? ValidatedResult { get; private set; } /// Der erfolgreich validierte Schlüssel (für die verschlüsselte Ablage). public string? ValidatedKey { get; private set; } /// /// true = Aufruf beim Programmstart (keine gültige Lizenz): der Abbruch-Button bietet /// „eingeschränkt starten". false = Aufruf aus den Einstellungen (App läuft bereits): der /// Button heißt „Schließen". /// public LicenseDialog(LicenseClient client, string prefillKey, LicenseResult? initialResult, bool startupContext = true) { _client = client ?? throw new ArgumentNullException(nameof(client)); InitializeComponent(); txtHardwareId.Text = SafeHardwareId(client); txtKey.Text = prefillKey ?? string.Empty; if (initialResult != null) { lblStatus.Text = "Status: " + LicenseGate.Describe(initialResult) + (string.IsNullOrEmpty(initialResult.Message) ? string.Empty : $" – {initialResult.Message}"); } else { lblStatus.Text = "Status: noch nicht geprüft – bitte „Validieren“ klicken."; } if (startupContext) { lblHeadline.Text = "Für PolyTrader wird eine gültige Lizenz benötigt."; btnLimited.Text = "Ohne Lizenz starten (eingeschränkt)"; } else { lblHeadline.Text = "Lizenz prüfen / hinterlegen"; btnLimited.Text = "Schließen"; } btnValidate.Click += (_, _) => Validate(); btnCopyHwId.Click += (_, _) => CopyHardwareId(); btnLimited.Click += (_, _) => { DialogResult = DialogResult.Cancel; Close(); }; AcceptButton = btnValidate; } private static string SafeHardwareId(LicenseClient client) { try { return client.GetHardwareId(); } catch { return "(nicht ermittelbar)"; } } private void Validate() { string key = txtKey.Text.Trim(); if (string.IsNullOrWhiteSpace(key)) { lblResult.ForeColor = Color.Firebrick; lblResult.Text = "Bitte einen Lizenzschlüssel eingeben."; return; } btnValidate.Enabled = false; Cursor = Cursors.WaitCursor; lblResult.ForeColor = SystemColors.ControlText; lblResult.Text = "Prüfe Lizenz …"; lblResult.Refresh(); try { // Blockierend: das SDK nutzt durchgängig ConfigureAwait(false) → kein Deadlock auf dem // UI-Thread; der kurze Freeze (max. HTTP-Timeout) ist im modalen Startdialog vertretbar // und vermeidet jede Abhängigkeit vom WinForms-SynchronizationContext vor Application.Run. LicenseResult result = _client.ValidateAsync(key).GetAwaiter().GetResult(); if (result.IsUsable) { ValidatedResult = result; ValidatedKey = key; lblResult.ForeColor = Color.Green; lblResult.Text = "Lizenz gültig – PolyTrader startet."; DialogResult = DialogResult.OK; Close(); } else { lblResult.ForeColor = Color.Firebrick; string extra = string.IsNullOrEmpty(result.Message) ? string.Empty : $" ({result.Message})"; lblResult.Text = "Nicht gültig: " + LicenseGate.Describe(result) + extra; } } catch (Exception ex) { lblResult.ForeColor = Color.Firebrick; lblResult.Text = "Fehler bei der Prüfung: " + ex.Message; } finally { Cursor = Cursors.Default; btnValidate.Enabled = true; } } private void CopyHardwareId() { try { Clipboard.SetText(txtHardwareId.Text); } catch { /* Zwischenablage kann kurzzeitig belegt sein – kein harter Fehler */ } } } }