using DatenDB; using Deckungsbeitrag.AA_Forms; using Deckungsbeitrag.AA_Klassen; using Deckungsbeitrag.Properties; using Microsoft.Win32; using System; using System.Collections.Generic; using System.Configuration; using System.Diagnostics; using System.Drawing; using System.IO; using System.Linq; using System.Management; using System.Net; using System.Reflection; using System.Runtime; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Security.Cryptography.X509Certificates; using System.Text; using System.Text.RegularExpressions; using System.Threading; using System.Threading.Tasks; using System.Timers; using System.Web.Configuration; using System.Web.SessionState; using System.Windows.Forms; namespace Deckungsbeitrag { public enum Priority { None = 0, First = 1, Second = 2, Third = 3, Fourth = 4, Fifth = 5 } // Globale Touch-Info (static für alle Forms) public static class TouchHelper { [DllImport("user32.dll")] private static extern int GetSystemMetrics(int nIndex); [DllImport("user32.dll", SetLastError = true)] private static extern uint GetRawInputDeviceList(IntPtr pRawInputDeviceList, ref uint puiNumDevices, uint cbSize); [DllImport("user32.dll", SetLastError = true)] private static extern uint GetRawInputDeviceInfo(IntPtr hDevice, uint uiCommand, IntPtr pData, ref uint pcbSize); private const int SM_DIGITIZER = 94; private const int SM_MAXIMUMTOUCHES = 95; private const int SM_CONVERTIBLESLATEMODE = 125; private const int RIM_TYPEKEYBOARD = 1; [StructLayout(LayoutKind.Sequential)] private struct RAWINPUTDEVICELIST { public IntPtr hDevice; public uint dwType; } public static readonly bool HasTouchHardware = (GetSystemMetrics(SM_DIGITIZER) & 0x80) != 0; public static readonly int TouchPoints = GetSystemMetrics(SM_MAXIMUMTOUCHES); public static readonly bool IsTabletMode = GetSystemMetrics(SM_CONVERTIBLESLATEMODE) == 1; public static bool IsTouchActive() { if (IsRegistryDisabled()) return false; if (TouchPoints <= 0) return false; int digitizer = GetSystemMetrics(SM_DIGITIZER); bool touchReady = (digitizer & 0x00000001) != 0; bool penReady = (digitizer & 0x00000002) != 0; return touchReady || penReady; } public static bool IsTouchDeviceReady() => HasTouchHardware && IsTouchActive(); private static bool IsRegistryDisabled() { using (RegistryKey key = Registry.CurrentUser.OpenSubKey(@"Software\Microsoft\Wisp\TouchGate")) { if (key != null) { object value = key.GetValue("TouchGate"); return value != null && Convert.ToInt32(value) == 0; } } return false; } public static string GetStatus() { return $"Hardware: {HasTouchHardware}, TouchActive: {IsTouchActive()}, Points: {TouchPoints}, TabletMode: {IsTabletMode}"; } } static class Program { private static Mutex mutex; public static Color Wirlblau = Settings.Default.Wirlblau; public static ImageList imagelist = new ImageList(); public static string userid; public static Benutzer benutzer; public static bool Artikelliste_Importiert = false; public static bool Kundenliste_Importiert = false; public static bool Software_Updated = false; private static readonly DateTime zielZeit = new DateTime(DateTime.Today.Year, DateTime.Today.Month, DateTime.Today.Day, 22, 0, 0); private static System.Timers.Timer timer; //public static string vaultPath = @"N:\TECHNIK\Software\Wirl-Verwaltung\Feedback"; private static readonly string savePath = ConfigurationManager.AppSettings["DateiSavePfad"]; private static readonly bool istest = false; public static bool istTouch = TouchHelper.IsTouchDeviceReady(); public static int scrollBar = 25; /// /// Der Haupteinstiegspunkt für die Anwendung. /// [STAThread] static void Main() { userid = ConfigurationManager.AppSettings["ConnectionString"].Split(';')[0]; userid = userid.Split('=')[1]; timer = new System.Timers.Timer { Interval = 1000 }; timer.Elapsed += Timer_Elapsed; timer.Start(); Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); Screen[] screens = Screen.AllScreens; Application.UseWaitCursor = true; string assemblyGUID = Assembly.GetExecutingAssembly().GetCustomAttributes(typeof(GuidAttribute), false).Cast().First().Value; mutex = new Mutex(true, $"Global\\{assemblyGUID}"); if (!mutex.WaitOne(TimeSpan.Zero, true)) { MessageBox.Show("Diese Anwendung ist bereits laufend. Nur eine Instanz darf gleichzeitig ausgeführt werden.", "Nur eine Instanz", MessageBoxButtons.OK, MessageBoxIcon.Exclamation); return; } // Check, Install und Update wenn Update vorhanden. if (CheckAndInstallUpdate()) { MessageBox.Show("Update wurde erfolgreich durchgeführt.\nStarte das Programm über den Desktop neu.", "UPDATE INFO", MessageBoxButtons.OK, MessageBoxIcon.Information); Software_Updated = true; Settings.Default.LastSoftwareUpdate = DateTime.Now; Application.UseWaitCursor = false; return; } // Laden der Image-Liste mit Icons für ObjectListView in Export etc. ImageList_Laden(); // Importieren und Updaten der Kundenliste wenn Datei vorhanden. KundenList_Laden(); // Importieren und Updaten der Artikelliste wenn Datei vorhanden. ArtikelList_Laden(); // EINMALIG BEI SWITCH AUF NW_Artikel DateTime timestamp = DateTime.Today; List artikellist = Artikel.GetArtikelList("MitNachwaesche"); foreach (Artikel art in artikellist) { ArtikelNachwaesche nw = ArtikelNachwaesche.FindeDatensatz(art.ArtikelID, timestamp); if (nw.NachwaescheID != null) nw.Nachwaesche++; else { nw = new ArtikelNachwaesche() { ArtikelID = art.ArtikelID, Datum = timestamp, Nachwaesche = art.Nachwaesche }; } if (nw.Save() == 1) { art.Nachwaesche = 0; art.Save(); } } Settings.Default.Save(); Application.UseWaitCursor = false; if (istest) { Application.Run(new FormAufleger()); return; } if (userid.StartsWith("ms") | userid.StartsWith("ps")) { switch (userid) { case var s when s.Contains("wstrasse"): //benutzer = Benutzer.GetBenutzer(null, 4); Application.Run(new FormAufleger(userid)); break; case var s when s.Contains("frottee"): Application.Run(new FormFehlmengeCount(userid)); break; case var s when s.Contains("kleinteile"): Application.Run(new FormFehlmengeCount(userid)); break; case var s when s.Contains("grossteile"): Application.Run(new FormFehlmengeCount(userid)); break; case var s when s.Contains("spannleintuch"): Application.Run(new FormFehlmengeCount(userid)); break; default: break; } } else { // Öffnen der ReadMe wenn noch nicht geöffnet wurde. //Open_ReadMe(); FormLogin loginForm = new FormLogin(); if (loginForm.ShowDialog() == DialogResult.OK) { benutzer = loginForm.Person; // Switch on BenutzerRolle für Weiterleitung zum richtigen Screen switch (loginForm.Person.Rolle) { case BenutzerRolle.Verwaltung: //Büropersonal ohne aktive Hallenbeschäftigung Application.Run(new FormMain(loginForm.Person)); break; case BenutzerRolle.Fahrer: //Zustellfahrer Application.Run(new FormMain(loginForm.Person)); break; case BenutzerRolle.Admin: //Höheres Büropersonal oder Claudia und Kevin Application.Run(new FormMain(loginForm.Person)); break; case BenutzerRolle.Waschstrasse: //Bediener einer Waschstraße Application.Run(new FormNeuerAuftrag(loginForm.Person, AuftragTyp.Standart)); break; case BenutzerRolle.Master: //Entwickler oder Claudia und Kevin Application.Run(new FormMain(loginForm.Person)); break; case BenutzerRolle.Expedit: //Endkontrolle Lieferungen und Lieferscheine (Mirka) Application.Run(new FormExpedit(loginForm.Person, screens)); break; case BenutzerRolle.Frottee: //Containerbestückung Frotteewäsche //BenutzerRolle Frottee = Expedit Frottee da die Maschine keine Anmeldung erfordert. Application.Run(new FormExpedit(loginForm.Person, screens)); break; case BenutzerRolle.Flach: //Containerbestückung Flachwäsche //BenutzerRolle Flach = Expedit Frottee da die Maschine keine Anmeldung erfordert. Application.Run(new FormExpedit(loginForm.Person, screens)); break; default: break; } } } } #region private-Funktionen private static void TouchAppConfig() { // Globale Touch-Optimierungen // z.B. größere Buttons, Auto-Tastatur, etc. } private static void Open_ReadMe() { string readmePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Verwaltung_ReadMe.txt"); // Prüfe, ob ReadMe schon einmal geöffnet wurde using (RegistryKey key = Registry.CurrentUser.OpenSubKey(@"Software\KilianWirlGmbH\Verwaltung")) { if (key == null || key.GetValue("ReadMeShown") == null) { // Erstes Mal nach Installation if (File.Exists(readmePath)) { Process.Start(new ProcessStartInfo { FileName = readmePath, UseShellExecute = true }); // WICHTIG: Warte 2 Sekunden (ReadMe öffnen) System.Threading.Thread.Sleep(2000); // Abbruch-Dialog DialogResult result = MessageBox.Show( "ReadMe wurde geöffnet.\n\n" + "Falls INSTALL-REMINDER noch Änderungen enthält,\n" + "soll die Anwendung jetzt ABGEBROCHEN werden?\n\n" + "[JA = Abbruch | NEIN = Fortfahren]", "Nach Installation - Update prüfen", MessageBoxButtons.YesNo, MessageBoxIcon.Question, MessageBoxDefaultButton.Button1 // Standard: Abbruch ); if (result == DialogResult.Yes) { MessageBox.Show("Installation wurde abgebrochen.\nBitte Änderungen vornehmen und neu installieren.", "Abbruch", MessageBoxButtons.OK, MessageBoxIcon.Information); return; // App beenden } // Markiere als gezeigt Registry.CurrentUser.CreateSubKey(@"Software\KilianWirlGmbH\Verwaltung") .SetValue("ReadMeShown", 1); } } } } private static void Timer_Elapsed(object sender, ElapsedEventArgs e) { if (DateTime.Now >= zielZeit) { timer.Stop(); timer.Dispose(); Application.Exit(); // Schließt alle Forms und beendet die App } } private static void ArtikelList_Laden() { string updatePath = Path.Combine(savePath, "Listen"); string dateiName = "Artikelkurzliste.csv"; string row; string[] rows; try { // Prüfen ob File Artikelkurzliste existiert. if (File.Exists(Path.Combine(updatePath, dateiName))) { string filename = Path.Combine(updatePath, dateiName); StreamReader streamReader = new StreamReader(filename, Encoding.GetEncoding("iso-8859-1")); row = string.Empty; rows = new string[0]; int saved = 0; int tosave = 0; int idx = 1; while (!streamReader.EndOfStream) { Array.Resize(ref rows, idx); row = streamReader.ReadLine(); if (row.StartsWith("60") || row.StartsWith("10")) { rows[idx - 1] = row; idx++; } } streamReader.Close(); // Zeilen der Datei durchiterieren. foreach (string line in rows) { string[] linedata = line.Split(';'); // ArtikelGruppen 60 und 10 werden weiterverarbeitet. if (linedata[0] == "60" || linedata[0] == "10") { tosave++; // Artikel wird in DB gesucht und geholt. Artikel art = Artikel.GetArtikel(Convert.ToInt32(linedata[1]), null) ?? new Artikel(); art.Nummer = Convert.ToInt32(linedata[1]); art.Bezeichnung = linedata[3]; // Kategorie wird nach Artikelnummer zugeordnet. switch (art.Nummer) { case var nr when nr.ToString()[1] == '3': // 2.Stelle wird auf 3 überprüft art.Kategorie = ArtikelKategorie.Frottee; break; case var nr when nr.ToString()[1] == '1' & nr.ToString()[2] == '1': // 2. und 3. Stelle wird auf 1 überprüft if (nr.ToString()[4] == '5' || nr.ToString()[4] == '6') art.Kategorie = ArtikelKategorie.Spannleintuch; else art.Kategorie = ArtikelKategorie.Grossteile; break; case var nr when nr.ToString()[1] == '1' & nr.ToString()[2] == '2': // 2. und 3. Stelle wird auf 2 überprüft art.Kategorie = ArtikelKategorie.Kleinteile; break; default: break; } // Wenn Artikel Shortbezeichnung ist vorhanden dann leeren damit neue Bezeichnung erstellt werden kann. if (!string.IsNullOrWhiteSpace(art.Short)) art.Short = string.Empty; // Erstellen der Shortbezeichnung für Buttons etc. if (art.Bezeichnung.Contains("DOPPEL") | art.Bezeichnung.Contains("D-")) art.Short = art.Short + "D-"; if (art.Bezeichnung.Contains("SPANN")) art.Short = art.Short + "SP"; if (art.Bezeichnung.Contains("LEINTUCH")) art.Short = art.Short + "LT"; if (art.Bezeichnung.Contains("SPANN")) { string[] s = art.Bezeichnung.Split(' '); if (s.Length == 3) art.Short = art.Short + " " + s[2]; } //Farben zuordnen und zu Short hinzufügen if (art.Bezeichnung.Contains("HANDTUCH")) art.Short = art.Short + "HT"; if (art.Bezeichnung.Contains("DUSCHTUCH")) art.Short = art.Short + "DT"; if (art.Bezeichnung.Contains("BADETUCH")) art.Short = art.Short + "BT"; if (art.Bezeichnung.Contains("BADEVORLEGER")) art.Short = art.Short + "BV"; if (art.Bezeichnung.Contains("BADEMANTEL")) art.Short = art.Short + "BM"; if (art.Bezeichnung.Contains("SAUNATUCH")) art.Short = art.Short + "ST"; if (art.Bezeichnung.Contains("GESICHTSTUCH")) art.Short = art.Short + "GT"; if (art.Bezeichnung.Contains("POLSTERBEZUG")) { string extra; int index = art.Bezeichnung.IndexOf(" ") + 1; int length = art.Bezeichnung.IndexOf(" ", index + 1) - index; art.Short = art.Short + "PB"; if (index > 0 & length > 0) { extra = art.Bezeichnung.Substring(index, length); art.Short += " " + extra; } switch (art.Bezeichnung) { case var bez when bez.Contains("60x80"): art.Short = art.Short + " 60x80"; break; case var bez when bez.Contains("40x60"): art.Short = art.Short + " 40x60"; break; case var bez when bez.Contains("40x40"): art.Short = art.Short + " 40x40"; break; case var bez when bez.Contains("40x50"): art.Short = art.Short + " 40x50"; break; case var bez when bez.Contains("40x70"): art.Short = art.Short + " 40x70"; break; default: break; } } //Größen zuordnen und zu Short hinzufügen if (art.Bezeichnung.Contains("DECKENBEZUG")) { string extra; int index = art.Bezeichnung.IndexOf(" ") + 1; int length = art.Bezeichnung.IndexOf(" ", index + 1) - index; art.Short = art.Short + "DB"; if (index > 0 & length > 0) { extra = art.Bezeichnung.Substring(index, length); art.Short += " " + extra; } } if (art.Bezeichnung.Contains("TISCHTUCH")) { art.Short = art.Short + "TT"; int index = art.Bezeichnung.IndexOf("x"); if (index > 0) art.Short = art.Short + art.Bezeichnung.Substring(index - 4, 8); } //Tischtücher und Größen zuordnen und zu Short hinzufügen if (art.Bezeichnung.Contains("MUNDSERVIETTE")) art.Short = art.Short + "MS"; if (art.Bezeichnung.Contains("DECKSERVIETTE")) art.Short = art.Short + "DS"; if (art.Save() == 1) saved++; } } if (saved == tosave) { Artikelliste_Importiert = true; Settings.Default.LastArtikelUpdate = DateTime.Now; } } } catch (Exception ex) { MessageBox.Show($"Import fehlgeschlagen: {ex.Message}\nPfad: {updatePath}\nDatei: {dateiName}", "IMPORT FEHLER", MessageBoxButtons.OK, MessageBoxIcon.Warning); } finally { // Wenn alles funktioniert hat wird die Datei gelöscht. if (Artikelliste_Importiert) File.Delete(Path.Combine(updatePath, dateiName)); } } private static void KundenList_Laden() { string updatePath = Path.Combine(savePath, "Listen"); updatePath = @"N:\TECHNIK\Software\Wirl-Verwaltung\Listen"; //Pfad zu Listen string dateiName = "Kundenstammblatt.csv"; string row; string[] rows; try { // Prüfen ob File Kundenstammblatt existiert. if (File.Exists(Path.Combine(updatePath, dateiName))) { string filename = Path.Combine(updatePath, dateiName); StreamReader sr = new StreamReader(filename, Encoding.GetEncoding("iso-8859-1")); row = string.Empty; rows = new string[0]; int saved = 0; int tosave = 0; int idx = 0; while (!sr.EndOfStream) { Array.Resize(ref rows, ++idx); row = sr.ReadLine(); rows[idx - 1] = row; } sr.Close(); // Jede Zeile der Datei wird durchiteriert. foreach (string line in rows) { string[] linedata = line.Split(';'); // Wenn 1. Datensatz von linedata keine Zahlen sind oder 6. Datensatz Preisgruppe enthält wird Zeile ignoriert. if (!int.TryParse(linedata[0], out _)) continue; if (linedata[5].Contains("Preisgruppe")) continue; tosave++; // Kunde wird gesucht und aus DB geholt. Kunde kunde = Kunde.GetKunde(linedata[0], null, null) ?? new Kunde(); kunde.KundeNummer = linedata[0]; kunde.KundeGruppe = linedata[3]; kunde.PLZ = int.TryParse(linedata[4], out int tmp2) ? tmp2 : 00; kunde.KundeName = linedata[5]; kunde.KundeName2 = linedata[6]; kunde.Strasse = linedata[8]; kunde.Land = linedata[9]; kunde.Ort = linedata[10]; kunde.Bettenanzahl = int.TryParse(linedata[45], out int bett) ? bett : 0; kunde.Waescheart = linedata[46]; if (kunde.Waescheart == "Miete") kunde.HatNachwaesche = true; else kunde.HatNachwaesche = false; if (kunde.Service != linedata[47]) { if (MessageBox.Show($"Beim Kunde {kunde.KundeName} hat sich der Service geändert. Welcher Service soll gespeichert werden?\n\n{kunde.Service} => [JA]\n{linedata[47]} => [NEIN]", "SERVICE WÄHLEN", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.No) kunde.Service = linedata[47]; } kunde.Region = linedata[48]; if (kunde.Suchtext != linedata[55]) kunde.Suchtext = linedata[55]; kunde.Aktiv = linedata[56] == "1"; if (kunde.Save() == 1) saved++; } if (saved == tosave) { Kundenliste_Importiert = true; Settings.Default.LastKundeUpdate = DateTime.Now; } } } catch (Exception ex) { MessageBox.Show($"Import fehlgeschlagen: {ex.Message}\nPfad: {updatePath}\nDatei: {dateiName}", "IMPORT FEHLER", MessageBoxButtons.OK, MessageBoxIcon.Warning); } finally { // Wenn alles funktioniert hat wird die Datei gelöscht. if (Kundenliste_Importiert) File.Delete(Path.Combine(updatePath, dateiName)); } } private static bool CheckAndInstallUpdate() { string updatePath = Path.Combine(savePath, "Setup"); if (ConfigurationManager.AppSettings["ConnectionString"].Split(';')[4].Split('=')[1] == "Test_Wirl") updatePath = Path.Combine(ConfigurationManager.AppSettings["DateiSavePfad"], "Test") ?? "Test"; string currentVersion = Assembly.GetExecutingAssembly().GetName().Version.ToString(); //updatePath = @"N:\TECHNIK\Software\Wirl-Verwaltung\Setup"; // Ihr interner UNC-Pfad try { string newVersion = File.Exists(Path.Combine(updatePath, "Version.txt")) ? File.ReadAllText(Path.Combine(updatePath, "Version.txt")).Trim() : string.Empty; if (string.IsNullOrWhiteSpace(newVersion)) { // Alle msi Files auflisten. string[] msiFiles = Directory.GetFiles(updatePath, "SetupVerwaltung*.msi"); if (msiFiles.Length == 0) return false; // Neueste Version aus Dateiname finden string validMsis = msiFiles .Select(f => new { Path = f, Version = GetVersionFromMsiFilename(f) }) .Where(x => IsValidVersion(x.Version)) .OrderByDescending(x => new Version(x.Version)) .FirstOrDefault()?.Version; // Wenn Version ist valide wird sie als neue Version gführt. if (validMsis != null) newVersion = validMsis; } // Prüfen ob neue Version ist größer als aktuelle Version. if (new Version(newVersion).CompareTo(new Version(currentVersion)) > 0) { DialogResult result = MessageBox.Show( $"Update verfügbar: {newVersion}\nInstallieren?", "UPDATE VERFÜGBAR", MessageBoxButtons.YesNo, MessageBoxIcon.Question); string msiPath = Path.Combine(updatePath, $"SetupVerwaltung{newVersion}.msi"); if (result == DialogResult.Yes) { try { // 1. MSI lokal kopieren (umgeht UNC-Fehler 2203) string localMsi = Path.Combine(@"C:\tmp", $"SetupVerwaltung{newVersion}.msi"); File.Copy(msiPath, localMsi, true); // 2. MSI starten var psi = new ProcessStartInfo { FileName = "msiexec.exe", Arguments = $"/i \"{localMsi}\" /norestart ALLUSERS=1 /L*v \"C:\\tmp\\update.log\"", Verb = "runas", UseShellExecute = true }; // Prozesse und Programm schließen. // 1. SELBST schließen (wichtig!) Application.Exit(); // 2. ALLE Prozesse killen foreach (Process p in Process.GetProcessesByName("Deckungsbeitrag")) if (p.Id != Process.GetCurrentProcess().Id) p.Kill(); foreach (Process p in Process.GetProcessesByName("Wirl-Verwaltung")) p.Kill(); foreach (Process p in Process.GetProcessesByName("SetupVerwaltung")) p.Kill(); // 3. 10 Sekunden warten (Restart Manager) Thread.Sleep(10000); using (var proc = Process.Start(psi)) { proc.WaitForExit(); // Blockiert bis Installation beendet } //Process.Start(psi)?.Dispose(); return true; } catch (Exception ex) { MessageBox.Show($"Start fehlgeschlagen: {ex.Message}", "UPDATE FEHLER", MessageBoxButtons.OK, MessageBoxIcon.Warning); } } } } catch (Exception ex) { MessageBox.Show($"Update-Prüfung fehlgeschlagen: {ex.Message}\nPfad: {updatePath}", "UPDATE FEHLER", MessageBoxButtons.OK, MessageBoxIcon.Warning); AddFehler(null, ex.Message, ex.StackTrace, null); } return false; } private static string GetVersionFromMsiFilename(string msiFilePath) { string filename = Path.GetFileNameWithoutExtension(msiFilePath); // Pattern: SetupVerwaltung1.0.44.msi → 1.0.44 // Oder: SetupVerwaltung_v1_0_44.msi → 1.0.44 Match match = Regex.Match(filename, @"(\d+(?:\.\d+){2,3})"); if (match.Success) return match.Groups[1].Value; return "0.0.0"; // Fallback } private static bool IsValidVersion(string version) { return Version.TryParse(version, out _); } private static void ImageList_Laden() { imagelist.Images.Add(Resources.Exclamation_Red); imagelist.Images.Add(Resources.InformationSymbol_16x); imagelist.Images.Add("print", Resources.PrintTag1); imagelist.Images.Add("abschließen", Resources.checkmark); imagelist.Images.Add("dirt", Resources.dirt); imagelist.Images.Add("clean", Resources.clean); imagelist.Images.Add("close", Resources.Close_red_16x); } #endregion #region public-Funktion public static void InventurFertig(Auftrag auftrag) { string savePath = Path.Combine(ConfigurationManager.AppSettings["DateiSavePfad"], "Listen\\Inventuren") ?? "Inventuren"; if (ConfigurationManager.AppSettings["ConnectionString"].Split(';')[4].Split('=')[1] == "Test_Wirl") savePath = Path.Combine(ConfigurationManager.AppSettings["DateiSavePfad"], "Test\\Inventuren") ?? "Inventuren"; Kunde kunde = Kunde.GetKunde(null, auftrag.KundeID, null); string delPath = Path.Combine(savePath, $"Herrichten-{auftrag.AuftragID}-{kunde.KundeNummer}.csv"); string[] lines = null; if (File.Exists(delPath)) { lines = File.ReadAllLines(delPath, Encoding.UTF8); lines[7] += auftrag.AuftragID.ToString(); string fileName = $"Fertig-{auftrag.AuftragID}-{kunde.KundeNummer}.csv"; // Dateiname: Status-AuftragID-KundeNummer.csv string csvPath; csvPath = Path.Combine(savePath, fileName); var csv = new StringBuilder(); foreach (string line in lines) csv.AppendLine(line); File.WriteAllText(csvPath, csv.ToString(), Encoding.UTF8); if (File.Exists(delPath)) File.Delete(delPath); } } public static void AddFeedback(Benutzer user, string feedbackText, string bildDateiname, string timeStamp) { string vaultPath = Path.Combine(savePath, "Feedback\\VerwaltungFeedback.md"); Benutzer ben = benutzer; // Wenn User existiert wird dieser Verwendet. Sonst der bei Anmeldung registrierte Benutzer. if (user != null) ben = user; string feedback; // Wenn der Bilddateiname leer ist wird feedback ohne Bilddateiname erstellt. if (string.IsNullOrWhiteSpace(bildDateiname)) { feedback = $@"- [ ] **Zeitpunkt:** {timeStamp} **| User:** {ben.Vorname} {ben.Nachname} **| Text:** {feedbackText}{Environment.NewLine}"; } else feedback = $@" - [ ] **Zeitpunkt:** {timeStamp} **| User:** {ben.Vorname} {ben.Nachname} **| Text:** {feedbackText} **| Bild:** ![[{bildDateiname}.png]]{Environment.NewLine}"; // Test wenn Image mitgegeben wird wird es hier gespeichert. (Pfadprobleme) File.AppendAllText(vaultPath, feedback); } public static DialogResult ShowOnBoarding(string userid, OnboardingSchritt onBoardingArt) { FormOnBoarding formOnBoarding = new FormOnBoarding(userid.ToLower(), onBoardingArt); if (formOnBoarding.ShowDialog() == DialogResult.Cancel) return DialogResult.Cancel; else return DialogResult.OK; } /// /// Fehler werden in Obsidian Fehlerliste Importiert. /// /// wenn null dann in Program registrierter User /// Fehlertext aus Exception oder individuell erstellen /// wenn null wird StackTrace nicht eingefügt. Kann auch individuell verwendet werden (Ort des Fehlers) /// wenn null wird TimeStamp hier erstellt public static void AddFehler(Benutzer user, string fehlerText, string fehlerStackTrace, string timeStamp) { string path = Path.Combine(savePath, "Feedback"); string vaultPath = Path.Combine(path, "VerwaltungFehler.md"); Benutzer ben = benutzer; // Wenn User existiert wird dieser Verwendet. Sonst der bei Anmeldung registrierte Benutzer. if (user != null) ben = user; string benutzerKennung; if (ben == null) benutzerKennung = userid; else benutzerKennung = ben.Vorname + " " + ben.Nachname; if (timeStamp == null) timeStamp = DateTime.Now.ToString("dd.MM.yyyy-HH-mm"); //string bildPath = Path.Combine(savePath, bildDateiname); string fehler; // Wenn der Bilddateiname leer ist wird feedback ohne Bilddateiname erstellt. if (string.IsNullOrWhiteSpace(fehlerStackTrace)) { fehler = $@"- [ ] **Zeitpunkt:** {timeStamp} **| User:** {benutzerKennung} **| Fehler:** {fehlerText}{Environment.NewLine}"; } else { string filename = $"fehler-{timeStamp}.txt"; string txtfile = Path.Combine(path, filename); File.WriteAllText(txtfile, fehlerStackTrace); fehler = $@" - [ ] **Zeitpunkt:** {timeStamp} **| User:** {benutzerKennung} **| Fehler:** {fehlerText} **| StackTrace:** [[{filename}]]{Environment.NewLine}"; } // Test wenn Image mitgegeben wird wird es hier gespeichert. (Pfadprobleme) File.AppendAllText(vaultPath, fehler); } #endregion } } //DOEN: Mit AddFehler in Obsidian eine Fehlerliste betreiben. (Wichtige Infos feststellen und bereitstellen) //DONE: Mit AddFehler können Fehler aus try/chatch in Obsidian eingefügt werden. (Timestamp, PC-Name, Ex-Message)