Uživatelská data do %APPDATA%\Rozpisky místo vedle .exe
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>
This commit is contained in:
+11
-6
@@ -1,4 +1,4 @@
|
|||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Windows;
|
using System.Windows;
|
||||||
using System.Windows.Threading;
|
using System.Windows.Threading;
|
||||||
@@ -7,8 +7,9 @@ namespace Rozpisky
|
|||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Globální záchytná síť pro neošetřené výjimky – aplikace nesmí spadnout bez stopy.
|
/// 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> vedle .exe (stejný portable princip jako
|
/// Každá výjimka se zapíše do <c>error.log</c> v uživatelské složce
|
||||||
/// <c>cad.json</c>/<c>layout.json</c>) a uživateli se ukáže MessageBox. Výjimky na UI
|
/// (<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ý
|
/// (Dispatcher) vlákně se označí jako zpracované, takže aplikace běží dál – rozdělaný
|
||||||
/// projekt zůstane otevřený a jde uložit.
|
/// projekt zůstane otevřený a jde uložit.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -18,6 +19,10 @@ namespace Rozpisky
|
|||||||
{
|
{
|
||||||
base.OnStartup(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ů.
|
// Úklid diagnostického logu tisku, ať po měsících nenaroste do enormních rozměrů.
|
||||||
Cad.CadTiskService.UklidLog();
|
Cad.CadTiskService.UklidLog();
|
||||||
|
|
||||||
@@ -46,14 +51,14 @@ namespace Rozpisky
|
|||||||
{
|
{
|
||||||
string radek = $"[{DateTime.Now:yyyy-MM-dd HH:mm:ss}] {zdroj}: {ex?.ToString() ?? "(neznámá výjimka)"}"
|
string radek = $"[{DateTime.Now:yyyy-MM-dd HH:mm:ss}] {zdroj}: {ex?.ToString() ?? "(neznámá výjimka)"}"
|
||||||
+ Environment.NewLine + Environment.NewLine;
|
+ Environment.NewLine + Environment.NewLine;
|
||||||
File.AppendAllText(Path.Combine(AppContext.BaseDirectory, "error.log"), radek, Encoding.UTF8);
|
File.AppendAllText(Data.UzivatelskaData.Cesta("error.log"), radek, Encoding.UTF8);
|
||||||
}
|
}
|
||||||
catch { /* read-only složka apod. – MessageBox se ukáže i tak */ }
|
catch { /* nezapisovatelná složka apod. – MessageBox se ukáže i tak */ }
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void UkazChybu(Exception ex) => MessageBox.Show(
|
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" +
|
"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 vedle aplikace.",
|
$"{ex.Message}\n\nPodrobnosti jsou v souboru error.log ve složce\n{Data.UzivatelskaData.Slozka}",
|
||||||
"Neočekávaná chyba", MessageBoxButton.OK, MessageBoxImage.Error);
|
"Neočekávaná chyba", MessageBoxButton.OK, MessageBoxImage.Error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Text.Encodings.Web;
|
using System.Text.Encodings.Web;
|
||||||
using System.Text.Json;
|
using System.Text.Json;
|
||||||
using Rozpisky.Data;
|
using Rozpisky.Data;
|
||||||
@@ -7,9 +7,9 @@ namespace Rozpisky.Cad;
|
|||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Načítání/ukládání seznamu podporovaných CAD systémů + naposledy vybraného enginu do JSON souboru
|
/// Načítání/ukládání seznamu podporovaných CAD systémů + naposledy vybraného enginu do JSON souboru
|
||||||
/// <b>vedle .exe</b> (portable). Stejný princip jako <see cref="Data.CiselnikyStore"/> /
|
/// v <b>uživatelské složce</b> (<see cref="Data.UzivatelskaData"/>). CAD je vlastnost stroje
|
||||||
/// <see cref="Dxf.MapovaniStore"/>: CAD je vlastnost stroje (ne zakázky), takže výběr žije mimo
|
/// (ne zakázky), takže výběr žije mimo projekt a je společný všem projektům – a mimo instalační
|
||||||
/// projekt a je globální pro celou instalaci.
|
/// složku, aby o něj uživatel při přeinstalaci nepřišel.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static class CadEnginesStore
|
public static class CadEnginesStore
|
||||||
{
|
{
|
||||||
@@ -21,8 +21,8 @@ public static class CadEnginesStore
|
|||||||
Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping,
|
Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// <summary>Výchozí umístění: soubor vedle .exe (portable).</summary>
|
/// <summary>Výchozí umístění: uživatelská složka (viz <see cref="UzivatelskaData"/>).</summary>
|
||||||
public static string DefaultPath => Path.Combine(AppContext.BaseDirectory, SouborNazev);
|
public static string DefaultPath => UzivatelskaData.Cesta(SouborNazev);
|
||||||
|
|
||||||
/// <summary>Uložený výběr CADu: buď předdefinovaný engine (<see cref="VybranyProgId"/>), nebo
|
/// <summary>Uložený výběr CADu: buď předdefinovaný engine (<see cref="VybranyProgId"/>), nebo
|
||||||
/// ruční režim „Manuálně" (<see cref="RucniRezim"/> + <see cref="RucniProgId"/>). Režim a ruční
|
/// ruční režim „Manuálně" (<see cref="RucniRezim"/> + <see cref="RucniProgId"/>). Režim a ruční
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
@@ -196,14 +196,15 @@ public static class CadTiskService
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var cesta = Path.Combine(AppContext.BaseDirectory, "tisk_diag.log");
|
var cesta = Data.UzivatelskaData.Cesta("tisk_diag.log");
|
||||||
if (File.Exists(cesta) && new FileInfo(cesta).Length > MaxLogBajtu)
|
if (File.Exists(cesta) && new FileInfo(cesta).Length > MaxLogBajtu)
|
||||||
File.Delete(cesta);
|
File.Delete(cesta);
|
||||||
}
|
}
|
||||||
catch { /* read-only složka apod. – úklid nesmí přerušit start */ }
|
catch { /* read-only složka apod. – úklid nesmí přerušit start */ }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>Diagnostický „chlebníček“ – zapíše krok tisku do <c>tisk_diag.log</c> vedle .exe.
|
/// <summary>Diagnostický „chlebníček“ – zapíše krok tisku do <c>tisk_diag.log</c>
|
||||||
|
/// v uživatelské složce.
|
||||||
/// Slouží k lokalizaci tvrdého pádu CADu (nativní chyba v <c>PlotToFile</c>), který nezanechá
|
/// Slouží k lokalizaci tvrdého pádu CADu (nativní chyba v <c>PlotToFile</c>), který nezanechá
|
||||||
/// stopu v error.log ani v log okně (obojí zmizí s procesem). Zapisuje se synchronně (flush ihned),
|
/// stopu v error.log ani v log okně (obojí zmizí s procesem). Zapisuje se synchronně (flush ihned),
|
||||||
/// takže poslední řádek přežije i pád procesu. Diagnostika sama nesmí nic shodit.</summary>
|
/// takže poslední řádek přežije i pád procesu. Diagnostika sama nesmí nic shodit.</summary>
|
||||||
@@ -211,7 +212,7 @@ public static class CadTiskService
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
File.AppendAllText(Path.Combine(AppContext.BaseDirectory, "tisk_diag.log"),
|
File.AppendAllText(Data.UzivatelskaData.Cesta("tisk_diag.log"),
|
||||||
$"[{DateTime.Now:yyyy-MM-dd HH:mm:ss.fff}] {krok}{Environment.NewLine}");
|
$"[{DateTime.Now:yyyy-MM-dd HH:mm:ss.fff}] {krok}{Environment.NewLine}");
|
||||||
}
|
}
|
||||||
catch { /* read-only složka apod. – nesmí přerušit tisk */ }
|
catch { /* read-only složka apod. – nesmí přerušit tisk */ }
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Text.Encodings.Web;
|
using System.Text.Encodings.Web;
|
||||||
using System.Text.Json;
|
using System.Text.Json;
|
||||||
using Rozpisky.Data;
|
using Rozpisky.Data;
|
||||||
@@ -6,8 +6,8 @@ using Rozpisky.Data;
|
|||||||
namespace Rozpisky.Cad;
|
namespace Rozpisky.Cad;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Načítání/ukládání <see cref="LayoutConfig"/> do JSON souboru <b>vedle .exe</b> (portable). Stejný
|
/// Načítání/ukládání <see cref="LayoutConfig"/> do JSON souboru v <b>uživatelské složce</b>
|
||||||
/// princip jako <see cref="CadEnginesStore"/> – konfigurace layoutů/tisku je vlastnost stroje/instalace
|
/// (<see cref="Data.UzivatelskaData"/>). Stejný princip jako <see cref="CadEnginesStore"/> – konfigurace layoutů/tisku je vlastnost stroje/instalace
|
||||||
/// (bloky a hladiny šablony, dostupné tiskárny), needituje se přes UI, jen ručně v souboru.
|
/// (bloky a hladiny šablony, dostupné tiskárny), needituje se přes UI, jen ručně v souboru.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static class LayoutConfigStore
|
public static class LayoutConfigStore
|
||||||
@@ -20,8 +20,8 @@ public static class LayoutConfigStore
|
|||||||
Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping,
|
Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// <summary>Výchozí umístění: soubor vedle .exe (portable).</summary>
|
/// <summary>Výchozí umístění: uživatelská složka (viz <see cref="UzivatelskaData"/>).</summary>
|
||||||
public static string DefaultPath => Path.Combine(AppContext.BaseDirectory, SouborNazev);
|
public static string DefaultPath => UzivatelskaData.Cesta(SouborNazev);
|
||||||
|
|
||||||
/// <summary>Načte konfiguraci. Když soubor chybí/je poškozený, vrátí vestavěné výchozí hodnoty
|
/// <summary>Načte konfiguraci. Když soubor chybí/je poškozený, vrátí vestavěné výchozí hodnoty
|
||||||
/// (a rovnou je uloží, aby šel soubor dál ručně upravovat).</summary>
|
/// (a rovnou je uloží, aby šel soubor dál ručně upravovat).</summary>
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Windows;
|
using System.Windows;
|
||||||
|
|
||||||
namespace Rozpisky.Data;
|
namespace Rozpisky.Data;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Společné zacházení s JSON konfiguračními soubory vedle .exe (<c>ciselniky.json</c>,
|
/// Společné zacházení s JSON konfiguračními soubory (<c>ciselniky.user.json</c>, <c>cad.json</c>,
|
||||||
/// <c>cad.json</c>, <c>layout.json</c>, <c>mapovani.json</c>). Řeší dvě slabiny přímého
|
/// <c>layout.json</c> v uživatelské složce, <c>mapovani.json</c> vedle .exe). Řeší dvě slabiny přímého
|
||||||
/// <c>File.WriteAllText</c>: pád uprostřed zápisu nesmí poškodit původní soubor (atomický zápis
|
/// <c>File.WriteAllText</c>: pád uprostřed zápisu nesmí poškodit původní soubor (atomický zápis
|
||||||
/// přes .tmp) a poškozený soubor se nesmí tiše zahodit – ručně editovaný config s překlepem by se
|
/// přes .tmp) a poškozený soubor se nesmí tiše zahodit – ručně editovaný config s překlepem by se
|
||||||
/// jinak bez varování přepsal výchozími hodnotami a uživatel by přišel o vlastní data.
|
/// jinak bez varování přepsal výchozími hodnotami a uživatel by přišel o vlastní data.
|
||||||
@@ -41,7 +41,7 @@ public static class JsonConfigFile
|
|||||||
(zaloha is null
|
(zaloha is null
|
||||||
? "Zálohu původního souboru se nepodařilo vytvořit."
|
? "Zálohu původního souboru se nepodařilo vytvořit."
|
||||||
: $"Původní obsah je zálohovaný v:\n{zaloha}") +
|
: $"Původní obsah je zálohovaný v:\n{zaloha}") +
|
||||||
"\n\nPodrobnosti jsou v souboru error.log vedle aplikace.";
|
$"\n\nPodrobnosti jsou v souboru error.log ve složce\n{UzivatelskaData.Slozka}";
|
||||||
// BeginInvoke: hláška se ukáže až po rozběhnutí UI smyčky (config se čte před oknem).
|
// BeginInvoke: hláška se ukáže až po rozběhnutí UI smyčky (config se čte před oknem).
|
||||||
Application.Current?.Dispatcher.BeginInvoke(() =>
|
Application.Current?.Dispatcher.BeginInvoke(() =>
|
||||||
MessageBox.Show(zprava, "Poškozený konfigurační soubor",
|
MessageBox.Show(zprava, "Poškozený konfigurační soubor",
|
||||||
@@ -54,7 +54,7 @@ public static class JsonConfigFile
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
File.AppendAllText(Path.Combine(AppContext.BaseDirectory, "error.log"),
|
File.AppendAllText(UzivatelskaData.Cesta("error.log"),
|
||||||
$"[{DateTime.Now:yyyy-MM-dd HH:mm:ss}] Config: {text}{Environment.NewLine}{Environment.NewLine}",
|
$"[{DateTime.Now:yyyy-MM-dd HH:mm:ss}] Config: {text}{Environment.NewLine}{Environment.NewLine}",
|
||||||
Encoding.UTF8);
|
Encoding.UTF8);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,60 @@
|
|||||||
|
using System.IO;
|
||||||
|
|
||||||
|
namespace Rozpisky.Data;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Jednorázový přesun dat starších verzí, které zapisovaly vedle .exe, do uživatelské složky
|
||||||
|
/// (<see cref="UzivatelskaData"/>). Bez toho by uživatel po aktualizaci našel prázdné číselníky
|
||||||
|
/// a přenastavený CAD. Volá se jednou při startu, ještě než si na data sáhne kterýkoli store.
|
||||||
|
/// <para>
|
||||||
|
/// Zásada: nikdy nic nemazat a nikdy nepřepsat novější data. Soubor se přenese jen tehdy, když
|
||||||
|
/// v cíli ještě není; originál zůstane ležet jako <c>*.migrovano</c> (jediná kopie uživatelových dat).
|
||||||
|
/// Selhání nesmí shodit start – horší než nepřenesená data je aplikace, která nenaběhne.
|
||||||
|
/// </para>
|
||||||
|
/// </summary>
|
||||||
|
public static class Migrace
|
||||||
|
{
|
||||||
|
/// <summary>Přípona, kterou dostane původní soubor po přenesení.</summary>
|
||||||
|
public const string PriponaHotovo = ".migrovano";
|
||||||
|
|
||||||
|
/// <summary>Přenese <c>cad.json</c> a <c>layout.json</c> ze složky aplikace do uživatelské.
|
||||||
|
/// Číselníky mají vlastní cestu (rozpad na vrstvy) – viz <see cref="CiselnikyStore"/>.</summary>
|
||||||
|
public static void PrenesStaraData()
|
||||||
|
{
|
||||||
|
Prenes(CadEnginesStoreNazev);
|
||||||
|
Prenes(LayoutConfigStoreNazev);
|
||||||
|
}
|
||||||
|
|
||||||
|
private const string CadEnginesStoreNazev = "cad.json";
|
||||||
|
private const string LayoutConfigStoreNazev = "layout.json";
|
||||||
|
|
||||||
|
/// <summary>Přesune soubor ze složky aplikace do uživatelské, pokud tam ještě není.
|
||||||
|
/// V portable režimu jsou obě složky totožné a neudělá se nic.</summary>
|
||||||
|
private static void Prenes(string nazevSouboru)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var zdroj = Path.Combine(AppContext.BaseDirectory, nazevSouboru);
|
||||||
|
var cil = UzivatelskaData.Cesta(nazevSouboru);
|
||||||
|
if (string.Equals(zdroj, cil, StringComparison.OrdinalIgnoreCase)) return;
|
||||||
|
if (!File.Exists(zdroj) || File.Exists(cil)) return;
|
||||||
|
|
||||||
|
File.Copy(zdroj, cil);
|
||||||
|
OznacJakoPrenesene(zdroj);
|
||||||
|
}
|
||||||
|
catch (Exception ex) when (ex is IOException or UnauthorizedAccessException)
|
||||||
|
{
|
||||||
|
// Nezapisovatelná instalační složka apod. – data zůstanou tam, kde jsou, a zkusí se
|
||||||
|
// přenést zase příště. Start aplikace to zastavit nesmí.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>Přejmenuje původní soubor na <c>*.migrovano</c>, aby se přenos neopakoval a aby
|
||||||
|
/// starší verze programu (kdyby ji uživatel vrátil) nezmátla už neaktuální data. Nedaří-li se
|
||||||
|
/// to (soubor jen pro čtení), nevadí – kopie v cíli už existuje a další běh přenos přeskočí.</summary>
|
||||||
|
internal static void OznacJakoPrenesene(string cesta)
|
||||||
|
{
|
||||||
|
try { File.Move(cesta, cesta + PriponaHotovo, overwrite: true); }
|
||||||
|
catch (Exception ex) when (ex is IOException or UnauthorizedAccessException) { }
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,53 @@
|
|||||||
|
using System.IO;
|
||||||
|
|
||||||
|
namespace Rozpisky.Data;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Jediné místo pro data, která píše <b>uživatel</b> (číselníky, výběr CADu, konfigurace layoutů,
|
||||||
|
/// logy). Leží v profilu uživatele (<c>%APPDATA%\Rozpisky</c>), ne vedle .exe – přeinstalace novou
|
||||||
|
/// verzí ani .exe v <c>Program Files</c> (jen pro čtení) je tak nemůžou zničit.
|
||||||
|
/// <para>
|
||||||
|
/// Podklady <b>dodávané</b> s programem (šablona, mustr, loga, výchozí číselníky, mapování) zůstávají
|
||||||
|
/// vedle .exe a čtou se přes <see cref="AppContext.BaseDirectory"/> – 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.
|
||||||
|
/// </para>
|
||||||
|
/// <para>
|
||||||
|
/// <b>Portable režim:</b> leží-li vedle .exe soubor <c>portable.txt</c>, vrátí se složka aplikace.
|
||||||
|
/// Slouží k běhu z USB a k vývoji, kdy je pohodlnější mít všechno v jedné složce s buildem.
|
||||||
|
/// </para>
|
||||||
|
/// </summary>
|
||||||
|
public static class UzivatelskaData
|
||||||
|
{
|
||||||
|
/// <summary>Značka portable režimu vedle .exe (obsah souboru se neřeší, stačí že existuje).</summary>
|
||||||
|
public const string PortableZnacka = "portable.txt";
|
||||||
|
|
||||||
|
private const string NazevSlozky = "Rozpisky";
|
||||||
|
|
||||||
|
private static string? _slozka;
|
||||||
|
|
||||||
|
/// <summary>Složka pro zapisovaná data. Počítá se jednou za běh a při prvním použití se vytvoří.
|
||||||
|
/// Když se vytvořit nepodaří (výjimečné – profil uživatele je zapisovatelný), spadne se zpátky
|
||||||
|
/// na složku aplikace, ať se program aspoň spustí.</summary>
|
||||||
|
public static string Slozka => _slozka ??= UrciSlozku();
|
||||||
|
|
||||||
|
/// <summary>Plná cesta k souboru se zapisovanými daty.</summary>
|
||||||
|
public static string Cesta(string nazevSouboru) => Path.Combine(Slozka, nazevSouboru);
|
||||||
|
|
||||||
|
private static string UrciSlozku()
|
||||||
|
{
|
||||||
|
var vedleExe = AppContext.BaseDirectory;
|
||||||
|
if (File.Exists(Path.Combine(vedleExe, PortableZnacka))) return vedleExe;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var slozka = Path.Combine(
|
||||||
|
Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), NazevSlozky);
|
||||||
|
Directory.CreateDirectory(slozka);
|
||||||
|
return slozka;
|
||||||
|
}
|
||||||
|
catch (Exception ex) when (ex is IOException or UnauthorizedAccessException)
|
||||||
|
{
|
||||||
|
return vedleExe;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user