Vítejte na blog.vyvojar.cz Přihlásit | Registrovat | Pomoc
Titulní Blogy Fotky Soubory

ZazaBlog

Kam s konfigurací .NETové aplikace?

Programátor píšící cokoli většího než je konzolová aplikace na pár řádečků dříve nebo později narazí na problém - kam ukládat konfigurační údaje, které aplikace pro svůj běh potřebuje. Způsobů je několik a každý z nich má své pro a proti. Pojďme se podívat na ty nejznámější z nich.

INI soubory

Už od dřevních dob používaly programy k uložení konfigurace tzv. ini soubory. Byly to textové soubory, typicky uložené v adresáři aplikace a směly obsahovat jednu či více sekcí a v každé sekci pak parametry. Čili, mohlo to vypadat nějak takto:

[Config]
server=localhost
user=sa
database=master

[Export]
format=txt
Savepath=D:

Jako hlavní výhodu ini souborů bych viděl jejich jednoduchost, jako hlavní nevýhodu vnímám to, že .NET je nepodporuje nativně. Je třeba použít staré triky a naimportovat si funkce z kernel32.dll:

Private Declare Ansi Function GetPrivateProfileString _

  Lib "kernel32.dll" Alias "GetPrivateProfileStringA" _

  (ByVal lpApplicationName As String, _

  ByVal lpKeyName As String, ByVal lpDefault As String, _

  ByVal lpReturnedString As System.Text.StringBuilder, _

  ByVal nSize As Integer, ByVal lpFileName As String) _

  As Integer

Nic moc, co?

Registry Windows

Ukládání informací do registrů je další dobrý a hojně používaný způsob zápisu konfigurace. Tento způsob má v .NET frameworku poměrně robustní podporu, takže můžete s pomocí Microsoft.Win32 psát něco ve smyslu:

regKey = Registry.LocalMachine.OpenSubKey("SOFTWARE\NODE\NODE\NODE", False)

umisteni = regKey.GetValue("KEY")

a obdobně pro ukládání. Ve prospěch používání registrů hovoří rovněž fakt, že do nich lze zapisovat již při instalaci (alespoň neznám žádný pokročilý instalátor, který by toto neuměl) a že pomocí nástroje regedit, který je k dispozici přímo v systému lze s registry manipulovat. Systém rovněž registry umí zálohovat a tak zazálohuje i Vaše nastavení, pokud jej registry obsahují.

Co mě od registru odrazuje je jeho chaotičnost. Jistě, systémové věci jsou tam kde mají být, ale aplikace třetích stran obvykle zapisují do registru stylem “každý pes jiná ves”.

VB.NET a jeho záložka Settings

Pokud pracujete (jako já) ve VB.NET, je k dispozici elegantní způsob ukládání konfigurace pomocí předpřipravených nástrojů, a to ve formě My.Settings. Systém je klikací, vygenerovaný kód obsahuje typovou kontrolu a interně je konfigurace uložena v XML souboru kdesi v uživatelském profilu. XML může vypadat nějak takto:

<?xml version="1.0" encoding="utf-8"?>

<configuration>

    <userSettings>

        <Program.My.MySettings>

            <setting name="LastUpdateCheck" serializeAs="String">

                <value>08/09/2009 14:30:53</value>

            </setting>

            <setting name="Verze" serializeAs="String">

                <value>0.1</value>

            </setting>

        </Pracant.My.MySettings>

    </userSettings>

</configuration>

Sympatické na tomto řešení je, že všechen kód pro ukládání a načítání konfigurace se generuje sám, uživatel pouze nakliká název a typ proměnné. Co mě na tomto způsobu ukládání hodnot odrazuje jsou dvě věci:

  1. Pokud se změní číslo verze assembly nebo jí dáte strong name, konfigurace se automaticky zahodí. Lze sice konfiguraci upgradovat z nižší verze, nicméně není to až tak triviální.
  2. Co je horší, program si ukládá soubory user.config do složek s kryptickými jmény (soubor výše mám například uložen ve složce "c:\Users\[profil]\AppData\Local\[firma]\[program].exe_StrongName_zygbcdzgwep1celxzqmkzrjfy20v3pkk\0.1.0.0" a neznám způsob, jak tuto cestu programově zjistit. To mimo jiné znamená, že nevím, jak přečíst nastavení cizí aplikace, což by se v reále mnohokrát hodilo a což by například v případě použití registrů bylo naprosto triviální.

Ukládání konfigurace do nějaké databáze

Při ukládání konfigurace do databáze musí programátor typicky napsat nějaký kód a vymyslet způsob, jak budou hodnoty v databázi uloženy. Mezi největší přínosy tohoto řešení patří fakt, že konfiguraci v databázi lze sdílet mezi více uživateli programu – což při použití předchozích metod je někdy složité a jindy zcela nemožné.

Mezi největší problémy patří to, že konfigurace z databáze je přístupná až po připojení k databázi. Pokud databáze ještě k dispozici není (například při startu programu nebo při selhání), konfiguraci nemusí jít načíst nebo uložit, a to může být problém.

Něco vlastního

Čas od času bývá k vidění rovněž nějaký vlastní systém – setkal jsem se například z projektem, který ukládal konfiguraci do XML souborů v adresáři aplikace. Vzhledem k tomu, že .NET obsahuje řadu nástrojů pro XML nemusí být tento způsob vůbec špatný. Výhodou je tedy jeho jednoduchost – co může být jednoduššího než:

Dim oXS As XmlSerializer = New XmlSerializer(obj.GetType)

Dim oStmW As StreamWriter

oStmW = New StreamWriter("konfigurace.xml")

oXS.Serialize(oStmW, obj)

oStmW.Close()

Na druhou stranu jako největší nevýhodu vnímám to, že tento způsob práce s konfigurací není nijak standardizován.

A jak řešíte ukládání konfigurace Vy, milí čtenáři?

Zveřejněno Sunday, August 09, 2009 3:44 PM by xzajic

Komentář

 

Chrasty napsal:

Já používám hlavně soubor app.config pomocí namespacu System.Configuration (což mi mimochodem v článku chybí, protože mi to přijde jako hlavní způsob pro ukládání nastavení v .NET desktop aplikacích).

August 9, 2009 5:07 PM
 

djanosik napsal:

Hádám, že zde nebyl uveden záměrně, protože není zrovna určen k provádění změn za běhu aplikace.

August 9, 2009 5:44 PM
 

xzajic napsal:

Partial Friend NotInheritable Class MySettings Inherits Global.System.Configuration.ApplicationSettingsBase

;-))

August 9, 2009 7:27 PM
 

JarinK napsal:

Je potreba rozlisovat mezi konfiguraci na urovni aplikace a jednotliveho uzivatele. Pro konfiguraci na urovni aplikace se standardne pouziva App.config/Web.config - slouzi k ukladani globalnich (sdilenych) nastaveni potrebnych k chodu aplikace, jako ConnectionString k databazi, adresa e-mailoveho serveru atd... Lze vytvaret vlastni konfiguracni sekce (odvozenim od System.Configuration.ConfigurationSection), lze take ulozit/obnovit konfiguraci za behu, konfig. soubor lze dokonce zasifrovat atd.

Standardni mechanismus pro ukladani nastaveni jednotlivych uzivatelu je jiz popsan v clanku v odstavci "VB.NET a jeho záložka Settings". Cesta ke konfiguracnimu souboru lze zjistit za behu z Application.LocalUserAppDataPath. Add 1) Konfigurace se nezahodi, pouze se pro novou verzi aplikace nacte vychozi konfigurace z App.config. Konfigurace predchozi verze je stale na svem miste... Diky teto vlastnosti lze spoustet paralelne vice verzi stejne aplikace, aniz by si vzajmene prepisovali konfigurace. Add 2) Nejak me nenapada, k cemu by bylo dobre prepisovat uzivatelske nastaveni cizich aplikaci... Nebylo by to naopak celkem spatne z pohledu bezpecnosti?

Dalsi moznosti, jak ulozit uzivatelske nastaveni je pomoci Isolated Storage - da se s vyhodou pouzit take pro aplikace/uzivatele, kteri maji omezena prava behu/zapisu. Vice informaci napr. zde (http://msdn.microsoft.com/en-us/library/bdts8hk0.aspx)

August 9, 2009 9:50 PM
 

xzajic napsal:

"Cesta ke konfiguracnimu souboru lze zjistit za behu z Application.LocalUserAppDataPath" - to bohužel ne. Vyzkoušejte si to.

"Přepisovat uživatelské nastavení cizích aplikací" - mě by ke štěstí kolikrát stačilo, kdybych je uměl přečíst. Pokud pracujete na příbuzných projektech, tak jste se s touto situací jistě také setkal. Například dva projekty sdílejí stejné připojení k databázi a podobně.

August 10, 2009 6:54 AM
 

JarinK napsal:

Vyzkousel jsem, funguje to. Tento zpusob funguje samozdrejme pouze pro Windows Forms aplikace. Application.LocalUserAppDataPath je pro lokalniho uzivatele, Application.UserAppDataPath potom pro uzivatele pouzivajiciho roaming profile. Dalsi zadrhel muze nastat, pokud pouzivate ClickOnce deployment, detaily si ale radeji nastudujte z MSDN.

Dalsi zpusob, jak zjistit cestu ke konfiguracnimu souboru uzivatele je pres ConfigurationManager tridu... Pridejte si do projeku assembly System.Configuration a pak zavolejte: Configuration config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.PerUserRoamingAndLocal);

Cesta k souboru je v config.FilePath.

Pokud chcete sdilet napr. udaje o pripojeni k databazi mezi aplikacemi, tak je urcite nebudete davat do uzivatelskeho konf. souboru, ale date je do konf. souboru aplikace (App.config), ktery je bezne ulozeny ve stejnem adresari jako vase aplikace, pod nazvem [JmenoAplikace].exe.config. Sdileni konfiguraci v App.config se da nastavit pomoci atributu configSource napr. takto: <connectionStrings configSource="databaze.config"></connectionStrings>, kde v souboru databaze.config bude konkretni connection string k vasi sdilene databazi. Doporucuji prostudovat System.Configuration z MSDN!

August 10, 2009 2:26 PM
 

viga napsal:

Ja jako vyvojar otazku "kam s konfiguraci" vubec neresim a nechavam tuto volbu na administratorovi. Pouzivam vseobecne znamy namespace System.Configuration a dodavam sadu konfiguracnich handleru (IConfigurationHandler), ktere umoznuji jakoukoliv sekci v app.config souboru natahnout z externiho zdroje (file, registry, command line, resources, database, atd.) Administrator si pak muze aplikaci nakonfigurovat jak se mu zlibi. Nektera nastaveni muzou sdilet vsechny pocitace a vsichni uzivatele prostrednictvim souboru umisteneho na siti, nektera muzou sdilet vsichni uzivatele na jednom pocitaci prostrednictvim registry, nektera muzou byt privatni pro uzivatele umistenim souboru do uzivatelskeho profilu nebo pouzitim registry klice current user a nektere nastaveni mohou byt dokonce privatni pro kazdou instanci predanim na command lajne. Nektera nastaveni mohou byt ulozena uz do resource a aplikace tak muze byt dodavana uz s nejakym implicitnim nastavenim aniz by u sebe musela mit nejaky dalsi konfiguracni soubor. A to vse bez toho aniz by se nad tim musel zamyslet vyvojar.

August 11, 2009 11:38 AM
 

xzajic napsal:

Tohle zní jako rajská hudba, nechtěl byste na tohle publikovat článeček někde na blogu?

August 11, 2009 11:49 AM
 

jskrobak napsal:

Programove se da cesta k souboru user.config zjistit takto: </br>

Configuration config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.PerUserRoamingAndLocal); </br>

Muzeme pak pracovat primo s oobjektem Config a nebo pouzit vlastnost config.FilePath k zjisteni absolutni cesty ke xml souboru.

August 13, 2009 8:13 AM
Neregistrovaní uživatele nemužou přidávat komentáře.
Powered by Community Server (Personal Edition), by Telligent Systems