Kontrola knihoven před spuštěním aplikace   zodpovězená otázka

C#, WinForms

Ahoj všem,

mám aplikaci (c# winforms, .NET 4.0), která používá pro generování PDF knihovnu iTextSharp. Standardně ji k aplikaci přibaluji,

ale stalo se, že si pár uživatelů "pročistilo adresář" a knihovna byla smazána.

Můj dotaz zní, zda je možné nějak při spouštění ověřit, že tam ta knihovna je. Zkoušel jsem File.Exist(),

ale to nefunguje, protože aplikace se nestihne spustit.

Díky.

nahlásit spamnahlásit spam 2 / 2 odpovědětodpovědět

A nestačilo by to File.Exists() pustit až před samotným pokusem o generování PDF?

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Nestacilo, protoze zavislosti se resi uz pri startu aplikace. Sam nevim jak by se to melo resit spravne. Kdyz jsem jednou neco takoveho potreboval, tak jsem tu knihovnu nepridaval do References ale nacital ji za behu pomoci Assembly.LoadFile (pokud knihovnu nelze najit, tak metoda vyhazuje vyjimku). Potom jsem tridy a metody z te knihovny pouzival pomoci typu dynamic (musel jsem znat presne nazvy a hlavne typy parametru a typy navratovych hodnot). Neprijemne na tomto je, ze se ztaci typova kontrola.

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Tak s tímhle nesouhlasím. Pokud Váš program nebude z referencované assembly nic volat, tak tam ta assembly být nemusí. Reference sama o sobě tomu nevadí.

Teprve v momentě, kdy v kódu bude volání, tak se vyhodí výjimka např.:

System.IO.FileNotFoundException: Could not load file or assembly 'itextsharp, Version=5.1.2.0, Culture=neutral, PublicKeyToken=8354ae6d2174ddca' or one of its dependencies. The system cannot find the file specified.
File name: 'itextsharp, Version=5.1.2.0, Culture=neutral, PublicKeyToken=8354ae6d2174ddca'
   at Form1.button1_Click(Object sender, EventArgs e)

Aby šla výjimka ošetřit, tak ale musí být kód používající tu assembly v jiné metodě např.:

private void button1_Click(object sender, EventArgs e)
{
    try
    {
        MessageBox.Show("Kod před použitím iTextSharp.");

        UseITextSharp();
    }
    catch (System.IO.FileNotFoundException ex)
    {
        MessageBox.Show(ex.ToString());
    }
}

private void UseITextSharp()
{
    var document = new Document();
}

private void button2_Click(object sender, EventArgs e)
{
    try
    {
        MessageBox.Show("Kod před použitím iTextSharp.");

        var document = new Document();
    }
    catch (System.IO.FileNotFoundException ex)
    {
        MessageBox.Show(ex.ToString());
    }
}

Kód tlačítka 1 zobrazí první MessageBox a pak ošetřenou vyjimku FileNotFoundException, kód tlačítka 2 způsobí, že aplikace zobrazí neošetřenou vyjimku FileNotFoundException (MessageBox se nezavolá).

nahlásit spamnahlásit spam 2 / 2 odpovědětodpovědět

Dejme tomu, že to tak je (nezkoušel jsem). Kolik lidí si myslíte, že to takto bude používat? Přináší to tolik komplikací, že to řešení je prakticky bezcenné, na druhou stranu se můžete plácat do kolen, že to jde.

nahlásit spamnahlásit spam -1 / 3 odpovědětodpovědět

Můžete si udělat metodu, která na tu knihovnu jen šáhne a k ničemu jinému než vyhazování výjimky nebude. Pak to plní přesně ten účel zkontrolovat jestli je možné knihovnu načíst.

nahlásit spamnahlásit spam 0 / 2 odpovědětodpovědět

Další a další bizardní nesmysly. Proč např. Office nebo jiný software se stovkami souborů nekontroluje, jestli některý nechybí??

nahlásit spamnahlásit spam -1 / 3 odpovědětodpovědět

Protože v program files se nikdo hrabat nemá. Pokud je ta aplikace distribuovaná jako zip, který si rozbalíte kam chcete, nebo nějak obdobně pak to možná smysl má. Zvlášť pokud už se tady tazatel setkal s případem, že by se to hodilo.

nahlásit spamnahlásit spam 1 / 3 odpovědětodpovědět

Člověče nepište už raději nic... To že se aplikace nenachází v Program Files ale jinde je důvod k tomu, aby se v ní kdekdo mohl rýt?

nahlásit spamnahlásit spam -1 / 3 odpovědětodpovědět

Tak jsem to zkoušel na jednom svém projektu. Nevím proč, ale některé knihovny to načítalo hned, jiné až když na ně šáhnu. Konkrétněji ty knihovny, které jsou součástí solution (a pak ještě Owin.Hosting a samozřejmě systémové knihovny) to načítalo hned a když tam nebyly, tak spadlo ještě předtím než se vykonal můj kód. Další (NuGet balíčky) knihovny to načítalo jak jste popisoval. Kdyby se to u ITextSharp chovalo obdobně, tak by to asi problém vyřešilo.

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Díky moc,

funguje to skvěle :)

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Jak už bylo řečeno, absenci knihoven, na něž je předem přidána reference si řeší Framework sám při spuštění aplikace a nelze to nijak ovlivnit.

Kontrolovat jestli si náhodou uživatel vlastní hloupostí program nějak nerozesral, např. smazáním knihoven nebo .config souborů je naprostá ztráta času, to už byste mohl řešit každou potenciální hovadinu, která může nastat.

A pro příště nepoužívejte formátování pro kód na běžný text příspěvku.

nahlásit spamnahlásit spam -1 / 3 odpovědětodpovědět

Ahoj, když si pročítám celou diskusi, tak mě jedině napadá klasická reflexe. Je to schopnost, když referenci nemusíte mít hned. Ale je otázkou zda se vám podaří tuto reflexi použít u dané knihovny, to bych nerad mátl. Ale jen přidávám možnost k zamyšlení.

nahlásit spamnahlásit spam 0 odpovědětodpovědět

To by samozřejmě šlo, ale je to hodně nepohodlné a ještě pomalé. Víceméně by se tomu musela přizpůsobit celá část aplikace, která tu knihovna používá, což je na nic.

Možná by šlo tu aplikaci spouštět nějakým skriptem, který by zkontroloval přítomnost všeho co je třeba a pak spustil.

nahlásit spamnahlásit spam 0 odpovědětodpovědět

V podstatě jste popsal jak se takováto situace řeší pomocí loaderu. Loader je aplikace která nejprve zkontroluje zda se všechny soubory a knihovny nacházejí na svém místě (a ve správné verzi). Pokud ano spustí samotný program, pokud ne tak je odněkud stáhne nebo vyhodí varování. Ale s použitím loaderu jsem se zatím setkal pouze u velkých online her (netvrdím že se nepoužívá i jinde). Ale příjde mi to jako jít s kanónem na vrabce. Navíc to stejně neřeší problém, kdy uživatel může aplikaci spustit a teprve potom se začne hrabat v aplikačních souborech, které začne měnit a promazávat. Taky jsem se setkal s jedním "pokročilým uživatelem" který si nejdřív smazal nějakou dll a když mu aplikace zarputile hlásila že se bez ní prostě nespustí, tak onen user vzal první dll kterou měl po ruce, zkopíroval ji na dané místo a přejmenoval na požadovaný název aby aplikace přestala otravovat. Ale ani se neptejte co se stalo když aplikace pak zkusila z té knihovny něco zavolat...

Podle mě pokud se nějaký koumák začne hrabat v aplikačních souborech, musí počítat s tím že mu ta aplikace dřív nebo později na něčem spadne.

nahlásit spamnahlásit spam 0 / 2 odpovědětodpovědět

Tak tu knihovnu přibalte do Vámi distribuované assembly pomocí ILMerge a nemusíte takové problémy vůbec řešit.

http://research.microsoft.com/en-us/peop...

Funguje to jen pro managed assembly, ale to Vy, předpokládám, máte.

nahlásit spamnahlásit spam 1 / 3 odpovědětodpovědět

Už jsem zde psal, že jsem odpůrce podobných prasáren, nicméně problém to řeší (do té doby, než se při potřebě rychlého sestavení a distribuce zapomene ilmergovat).

nahlásit spamnahlásit spam -2 / 2 odpovědětodpovědět
                       
Nadpis:
Antispam: Komu se občas házejí perly?
Příspěvek bude publikován pod identitou   anonym.
  • Administrátoři si vyhrazují právo komentáře upravovat či mazat bez udání důvodu.
    Mazány budou zejména komentáře obsahující vulgarity nebo porušující pravidla publikování.
  • Pokud nejste zaregistrováni, Vaše IP adresa bude zveřejněna. Pokud s tímto nesouhlasíte, příspěvek neodesílejte.

přihlásit pomocí externího účtu

přihlásit pomocí jména a hesla

Uživatel:
Heslo:

zapomenuté heslo

 

založit nový uživatelský účet

zaregistrujte se

 
zavřít

Nahlásit spam

Opravdu chcete tento příspěvek nahlásit pro porušování pravidel fóra?

Nahlásit Zrušit

Chyba

zavřít

feedback