Vše, co píše uživatel, míří přes novou třídu UzivatelskaData do profilu uživatele: cad.json, layout.json, error.log, tisk_diag.log. Dosud se zapisovalo vedle .exe, takže .exe v Program Files (složka jen pro čtení) nebo přeinstalace novou verzí uživatele o data připravily. Dodávané podklady (šablona, mustr, loga, mapovani.json) se dál čtou vedle .exe – ty se naopak při každé instalaci obnovují. Hranice mezi tím, co se instaluje, a tím, co patří uživateli, vede přesně tudy. Portable režim zůstává: soubor portable.txt vedle .exe vrátí staré chování (běh z USB, vývoj s jednou složkou). Migrace: Migrace.PrenesStaraData() při startu přenese cad.json a layout.json ze staré polohy, pokud v cíli ještě nejsou; originál označí příponou .migrovano. Nic se nemaže a nic novějšího se nepřepíše. Číselníky přijdou na řadu samostatně (rozpad na dodávanou a uživatelskou vrstvu). Build 0 chyb / 0 varování, 36 testů zelených. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
65 lines
2.9 KiB
C#
65 lines
2.9 KiB
C#
using System.IO;
|
||
using System.Text;
|
||
using System.Windows;
|
||
using System.Windows.Threading;
|
||
|
||
namespace Rozpisky
|
||
{
|
||
/// <summary>
|
||
/// Globální záchytná síť pro neošetřené výjimky – aplikace nesmí spadnout bez stopy.
|
||
/// Každá výjimka se zapíše do <c>error.log</c> v uživatelské složce
|
||
/// (<see cref="Data.UzivatelskaData"/>, stejně jako <c>cad.json</c>/<c>layout.json</c>)
|
||
/// a uživateli se ukáže MessageBox. Výjimky na UI
|
||
/// (Dispatcher) vlákně se označí jako zpracované, takže aplikace běží dál – rozdělaný
|
||
/// projekt zůstane otevřený a jde uložit.
|
||
/// </summary>
|
||
public partial class App : Application
|
||
{
|
||
protected override void OnStartup(StartupEventArgs e)
|
||
{
|
||
base.OnStartup(e);
|
||
|
||
// Data starších verzí ležela vedle .exe – přenést do uživatelské složky dřív,
|
||
// než si na ně sáhne kterýkoli store (ten už čte jen nové umístění).
|
||
Data.Migrace.PrenesStaraData();
|
||
|
||
// Úklid diagnostického logu tisku, ať po měsících nenaroste do enormních rozměrů.
|
||
Cad.CadTiskService.UklidLog();
|
||
|
||
DispatcherUnhandledException += (_, args) =>
|
||
{
|
||
ZalogujChybu("UI (Dispatcher)", args.Exception);
|
||
args.Handled = true; // aplikace přežije – projekt jde pořád uložit
|
||
UkazChybu(args.Exception);
|
||
};
|
||
|
||
// Výjimky mimo UI vlákno – proces už nejde zachránit, ale aspoň zůstane log.
|
||
AppDomain.CurrentDomain.UnhandledException += (_, args) =>
|
||
ZalogujChybu("AppDomain", args.ExceptionObject as Exception);
|
||
|
||
// Neodchycené výjimky z fire-and-forget Tasků – SetObserved zabrání eskalaci.
|
||
TaskScheduler.UnobservedTaskException += (_, args) =>
|
||
{
|
||
ZalogujChybu("Task (unobserved)", args.Exception);
|
||
args.SetObserved();
|
||
};
|
||
}
|
||
|
||
private static void ZalogujChybu(string zdroj, Exception? ex)
|
||
{
|
||
try
|
||
{
|
||
string radek = $"[{DateTime.Now:yyyy-MM-dd HH:mm:ss}] {zdroj}: {ex?.ToString() ?? "(neznámá výjimka)"}"
|
||
+ Environment.NewLine + Environment.NewLine;
|
||
File.AppendAllText(Data.UzivatelskaData.Cesta("error.log"), radek, Encoding.UTF8);
|
||
}
|
||
catch { /* nezapisovatelná složka apod. – MessageBox se ukáže i tak */ }
|
||
}
|
||
|
||
private static void UkazChybu(Exception ex) => MessageBox.Show(
|
||
"Nastala neočekávaná chyba, aplikace ale běží dál – doporučujeme uložit projekt.\n\n" +
|
||
$"{ex.Message}\n\nPodrobnosti jsou v souboru error.log ve složce\n{Data.UzivatelskaData.Slozka}",
|
||
"Neočekávaná chyba", MessageBoxButton.OK, MessageBoxImage.Error);
|
||
}
|
||
}
|