Grafikus C# – Windows Forms tanfolyam › 14.2 lecke

Windows Forms · 14.2 lecke · build

EXE, DLL, projekt- és kimeneti mappák

Lefordítottad a programot Release módban, és a bin\Release mappában egy tucat fájlt látsz. Melyik a program, melyik csak segédfájl, és mit kell átmásolnod egy másik gépre, hogy ott is fusson? Ha nem érted, mi micsoda, vagy túl keveset másolsz (a program nem indul), vagy mindent odaadsz, beleértve a fejlesztői fájlokat is. Ebben a leckében megismered a solution és a projekt felépítését, az EXE és a DLL szerepét, a kimeneti mappa fájljait (.deps.json, .runtimeconfig.json, .pdb, nyelvi almappák), azt, hogyan kerülnek az adatfájlok a kimenetbe, és hogyan ellenőrzöd tiszta gépen, hogy a programod önállóan működik.

  • kb. 90 perc
  • közepes szint
  • fájlok és mappák
Diák C# programozást gyakorol egy tanulósarokban

A lecke végére

  • elmagyarázod a solution (.sln), a projekt (.csproj) és az assembly fogalmát;
  • megkülönbözteted az EXE és a DLL szerepét;
  • tudod, mire való a kimeneti mappa minden fájlja;
  • eldöntöd, mit kell átadni a felhasználónak, és mit nem;
  • az adatfájlokat (kép, sablon, beállítás) beállítod, hogy a kimenetbe másolódjanak;
  • tiszta gépen (vagy mappában) ellenőrzöd, hogy a program önállóan fut.

Mielőtt elkezded

Ehhez a leckéhez a 14.1 lecke (Debug és Release) és a 12.9 lecke (solution, több projekt) szükséges.

14.1 Debug és Release →

Solution, projekt, assembly

A forrás mappája (amit fejlesztesz)mappák
Konyvtar\                          ← a solution mappa
Konyvtar.sln ← solution: a projektek gyűjteménye
Konyvtar.Core\ ← osztálykönyvtár projekt
Konyvtar.Core.csproj ← projektfájl: beállítások, hivatkozások
Models\, Services\ ... ← forráskódok (.cs)
Konyvtar.App\ ← Windows Forms projekt
Konyvtar.App.csproj
Form1.cs, Form1.Designer.cs, Program.cs
bin\, obj\ ← generált: fordítás eredménye (nem a forrás!)
FogalomMi ez?
Solution (.sln)Egy vagy több projekt gyűjteménye (12.9 lecke): a Visual Studio ezt nyitja meg.
Projekt (.csproj)Egy fordítási egység: a forrásfájlok, a hivatkozások és a build-beállítások (14.1 lecke).
AssemblyA fordítás eredménye: egy .exe vagy .dll fájl, amely a lefordított kódot (köztes nyelven, IL) és az adatait tartalmazza. Egy projekt = egy assembly.
Forrás és kimenetA forrás az, amit te írsz (.cs, .csproj, .resx): ezt tartod verziókezelésben (Git). A bin és obj mappa generált: bármikor újraépíthető, ezért nem tárolod (.gitignore).
HivatkozásokHa a Forms projekt a Core projektre hivatkozik (12.9 lecke), a fordítás a Core .dll fájlját a Forms kimeneti mappájába másolja: így a program mellett ott lesz a szükséges könyvtár.

EXE és DLL

EXE (futtatható)DLL (könyvtár)
SzerepA program belépési pontja (Main); indítható.Kódkönyvtár; nem indítható, más program tölti be.
Projekt típusaWindows Forms App (OutputType: WinExe), Konzolalkalmazás (Exe).Class Library (osztálykönyvtár).
PéldaKonyvtar.App.exeKonyvtar.Core.dll, System.Text.Json.dll, Microsoft.Data.Sqlite.dll
ÚjrahasználatNem hivatkozható (általában).Több program is használhatja ugyanazt a DLL-t.
Miért van DLL?A saját osztálykönyvtárad (Core) a logikát tartalmazza, és több felület is használhatja (WinForms, konzol, teszt). A harmadik féltől származó könyvtárak (NuGet, 14.4 lecke) is DLL-ek. A DLL-ek a program mellett vannak, és induláskor töltődnek be.
Mi az apphost?Az újabb .NET-ben a Program.exe egy kicsi indítóprogram (apphost), amely elindítja a futtatókörnyezetet, és betölti a valódi kódot tartalmazó Program.dll-t. Ezért található a mappában egyszerre Program.exe és Program.dll. Mindkettő kell.

Jósolj!

A felhasználónak csak a Konyvtar.App.exe fájlt másolod át, a mappa többi fájlját nem. Mi történik indításkor?

Jóslat ellenőrzése

A program nem indul: hiányzik a Konyvtar.App.dll (a valódi kód), a .runtimeconfig.json (melyik futtatókörnyezet kell) és a Konyvtar.Core.dll. Hibaüzenet: „A fájl nem található” vagy „FileNotFoundException: Could not load file or assembly...”. Az egész kimeneti mappát (a PDB nélkül) át kell adni, vagy a közzétételt (publish, 14.5 lecke) kell használni.

A kimeneti mappa fájljai

FájlMi ez?Átadni?
Program.exeAz indítóprogram (apphost).Igen
Program.dllA program lefordított kódja.Igen
Program.runtimeconfig.jsonMelyik .NET futtatókörnyezet és verzió kell a futtatáshoz.Igen
Program.deps.jsonA függőségek listája (milyen DLL-eket tölt be).Igen
Konyvtar.Core.dll, *.dll (NuGet)A hivatkozott könyvtárak.Igen
hu\, de\ ... mappákNyelvi erőforrások (satellite assemblies) a könyvtárakhoz.Igen (ha használt a program)
Program.pdbHibakereső szimbólumok.Nem kell (tartsd meg magadnak a hibakereséshez)
*.xml (dokumentáció)Fejlesztői dokumentáció.Nem
Adatfájlok (kép, sablon, .json beállítás)A programod által használt fájlok, ha a kimenetbe másoltad (lásd lent).Igen
Átadás: az egész mappaAz egyszerű átadás: az egész bin\Release\net8.0-windows mappa tartalma, a .pdb fájlok nélkül. A rendezettebb mód a Publish (14.5 lecke), amely pontosan a szükséges fájlokat gyűjti össze.
FuttatókörnyezetA .runtimeconfig.json megmondja, milyen .NET kell (például Microsoft.WindowsDesktop.App 8.0). Ha a gépen nincs telepítve, a program nem indul: a 14.3 lecke ezt tárgyalja.

Jósolj!

A felhasználó mappájából kitörlöd a Program.pdb fájlt. Elindul-e a program?

Jóslat ellenőrzése

Igen, a PDB a futáshoz nem szükséges: csak a hibakereséshez és a stack trace sorszámaihoz kell. Ezért nem kell átadnod a felhasználónak (és meg kell őrizned a saját archívumodban, hogy a hibajelentéseket értelmezni tudd).

Adatfájlok a kimenetben

Konyvtar.App.csprojXML
<ItemGroup>
<!-- a kép a fordításkor a kimeneti mappába másolódik (mindig, vagy csak ha újabb) -->
<None Update="Kepek\logo.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="Sablonok\*.txt">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
</ItemGroup>
Form1.csC#
// ROSSZ: a munkakönyvtár (Environment.CurrentDirectory) attól függ, HOGYAN indították a programot
string ut = Path.Combine(Environment.CurrentDirectory, "Kepek", "logo.png");

// JÓ: a program SAJÁT mappája (az exe helye)
string ut2 = Path.Combine(AppContext.BaseDirectory, "Kepek", "logo.png");

if (File.Exists(ut2)) { pbLogo.Image = Image.FromFile(ut2); } // és try–catch (13.6 lecke)
Copy to Output DirectoryAmi nem kód (kép, sablon, alap beállítás), azt a projektben jelölni kell: Copy to Output Directory → Copy if newer (Properties ablak), különben a fájl nem kerül a kimenetbe, és a program a másik gépen nem találja.
Munkakönyvtár a program mappája helyettA Environment.CurrentDirectory a program indításának helye (parancsikon, parancssor, Fájl megnyitása ablak is módosíthatja!). A saját fájljaidhoz az AppContext.BaseDirectory megbízható.
Ágyazott erőforrásAlternatíva: a kép beágyazott erőforrás (Resources.resx, 9. fejezet): az exe tartalmazza, nincs külön fájl, nincs hiányzó fájl. Kis ikonoknál és képeknél kényelmes.
Írható adat máshováA program mappájába (Program Files) általában nem írhatsz (13.6 lecke): a felhasználói adatok az ApplicationData mappába kerülnek; a program mappája csak olvasható adatoknak való.

Jósolj!

A program a Kepek\logo.png fájlt a munkakönyvtárból tölti. A fejlesztő gépen a Visual Studióból fut (jó), a felhasználó viszont egy parancsikonról indítja, amelynek munkakönyvtára az Asztal. Mit tapasztal?

Jóslat ellenőrzése

A program a Desktop\Kepek\logo.png fájlt keresi: nem találja (FileNotFoundException vagy üres kép). Az AppContext.BaseDirectory a program mappáját adja, függetlenül az indítás módjától.

📷 Képernyőkép helye

Mit tegyél ide: a Release kimeneti mappa fájljai, és a tulajdonságablak a Copy to Output Directory beállítással.Javasolt fájlnév: winforms-14-2-kimenet.webp · Alt szöveg: A kimeneti mappa fájljai

Hibakeresés: te vagy a hibadetektív

Mi a baj, és hogyan javítod?

Gondold végig az okot, és csak utána nyisd le a megoldást.

1. A másik gépen nem indul, nincs hibaüzenet

Csak az exe-t másoltad át.

Ok és javítás

Hiányzik a .dll és a .runtimeconfig.json. Add át a teljes kimeneti mappát (PDB nélkül), vagy használd a Publish-t (14.5 lecke).

2. FileNotFoundException: Could not load file or assembly

Egy könyvtár hiányzik a másik gépen.

Ok és javítás

A hivatkozott DLL nem másolódott át (vagy nem kerül a kimenetbe). Ellenőrizd a kimeneti mappa DLL-jeit, és a .deps.json függőségeit; NuGet csomagnál 14.4 lecke.

3. A kép nem jelenik meg a másik gépen

A fejlesztő gépen megjelenik, a felhasználónál üres.

Ok és javítás

Nem kerül a kimenetbe (nincs Copy to Output Directory), vagy a munkakönyvtárból töltöd. Állítsd be a másolást, és használd az AppContext.BaseDirectory-t.

4. A bin mappában régi fájlok vannak

Egy már törölt DLL még ott van, és a program használja.

Ok és javítás

Clean és Rebuild (14.1 lecke); átadás előtt tiszta mappából fordíts.

5. A program mappájába nem lehet írni

Telepítés után mentéskor UnauthorizedAccessException.

Ok és javítás

A program a saját (Program Files) mappájába ír. A felhasználói adatot az ApplicationData mappába tedd (13.6 lecke).

6. Az átadott mappa óriási

Több száz MB-ot kell másolni.

Ok és javítás

Debug kimenetet, PDB-ket, vagy önálló (self-contained) közzétételt adtál át. Release, PDB nélkül; a közzétételi módot a 14.5 lecke tárgyalja.

Mini projekt: kimeneti mappa vizsgálata és tiszta gépes próba

Készíts egy kis programot, amely önmagáról megmondja, hol fut, mely fájlok vannak mellette, és mely DLL-eket töltötte be; majd próbáld ki másik mappában (ideális esetben másik gépen):

  1. Solution: Vizsgalo.sln két projekttel: Vizsgalo.Core (osztálykönyvtár, egy Info osztállyal) és Vizsgalo.App (Windows Forms, hivatkozik a Core-ra).
  2. Adatfájlok: az App projektben legyen Kepek\logo.png és Sablonok\udvozlet.txt; állítsd mindkettőre a Copy to Output Directory: Copy if newer beállítást.
  3. Felület: lblHely (a program mappája), lstFajlok (a mappa fájljai), lstDll (betöltött assembly-k), pbLogo, txtSablon, lblUzenet.
  4. Kód: másold be a lenti megoldás kódját (az AppContext.BaseDirectory használatával, hibakezeléssel).
  5. Release fordítás: dotnet build -c Release vagy a Visual Studióból; nézd meg a bin\Release mappát, és sorold fel a fájlokat a leckében látott táblázat szerint (átadandó / nem).
  6. Átmásolás: másold az átadandó fájlokat (a .pdb nélkül) egy új, üres mappába (például C:\Teszt\Vizsgalo), és indítsd onnan.
  7. Hibatesztek: (a) hagyd ki a Vizsgalo.Core.dll fájlt; (b) hagyd ki a .runtimeconfig.json fájlt; (c) hagyd ki a Kepek mappát; (d) indítsd parancsikonról más munkakönyvtárral. Írd le mindegyik hibát (üzenet, ok).
  8. Tiszta gép: ha van rá lehetőséged, másold át egy másik számítógépre (vagy virtuális gépre), amelyen nincs fejlesztői környezet; jegyezd fel, mi hiányzik (a 14.3 lecke a .NET futtatókörnyezetről szól).
  9. Jegyzék: készíts átadási jegyzéket (táblázat): fájl, szerep, átadni?, mi történik, ha hiányzik.
Megoldás megnyitása (próbáld ki előbb önállóan!)
Form1.cs (using System.IO; using System.Linq; using System.Reflection;)C#
private void Form1_Load(object sender, EventArgs e)
{
string mappa = AppContext.BaseDirectory; // a program saját mappája, nem a munkakönyvtár

lblHely.Text = "Program mappa: " + mappa + Environment.NewLine + "Munkakönyvtár: " + Environment.CurrentDirectory;

try
{
foreach (string f in Directory.GetFiles(mappa).OrderBy(x => x)) { lstFajlok.Items.Add(Path.GetFileName(f) + " (" + new FileInfo(f).Length / 1024 + " KB)"); }
}
catch (Exception ex) when (ex is IOException || ex is UnauthorizedAccessException) { lblUzenet.Text = "A mappa nem olvasható: " + ex.Message; }

foreach (Assembly a in AppDomain.CurrentDomain.GetAssemblies().OrderBy(x => x.GetName().Name))
{
lstDll.Items.Add(a.GetName().Name + " " + a.GetName().Version);
}

lblUzenet.Text = "Core.Info: " + Vizsgalo.Core.Info.Uzenet(); // a Core.dll tényleges használata

string kep = Path.Combine(mappa, "Kepek", "logo.png");
string sablon = Path.Combine(mappa, "Sablonok", "udvozlet.txt");

try { using (Image tmp = Image.FromFile(kep)) { pbLogo.Image = new Bitmap(tmp); } } // a fájl nem marad zárolva
catch (Exception ex) when (ex is IOException || ex is ArgumentException || ex is OutOfMemoryException) { lblUzenet.Text += " | Kép: " + ex.Message; }

try { txtSablon.Text = File.ReadAllText(sablon); }
catch (Exception ex) when (ex is IOException || ex is UnauthorizedAccessException) { txtSablon.Text = "(a sablon nem található: " + Path.GetFileName(sablon) + ")"; }
}

// ---- Vizsgalo.Core/Info.cs ----
namespace Vizsgalo.Core
{
public static class Info { public static string Uzenet() { return "a Core.dll betöltődött (" + typeof(Info).Assembly.GetName().Version + ")"; } }
}

Várt tapasztalat: a hiányzó Core.dll miatt „Could not load file or assembly 'Vizsgalo.Core'” (a program a betöltéskor leáll); a hiányzó .runtimeconfig.json miatt az exe nem indul (futtatókörnyezet-hiba); a hiányzó Kepek mappa miatt a kód elkapja a hibát, és az üzenetsorban jelzi; a parancsikon eltérő munkakönyvtára a BaseDirectory miatt nem okoz hibát. A pontos hibaszövegek a Windows és a .NET verziótól függenek: jegyezd fel a sajátjaidat.

📷 Képernyőkép helye

Mit tegyél ide: a kész vizsgáló program (mappák, fájlok, betöltött DLL-ek) és az átadási jegyzék.Javasolt fájlnév: winforms-14-2-kesz.webp · Alt szöveg: A kimeneti mappa vizsgáló program

Három önálló gyakorlófeladat

Egyszerre csak egyet csinálj: tervezd meg, írd meg, futtasd, ellenőrizd, és csak utána nyisd ki a megoldást.

1. Saját átadási jegyzék

Készíts átadási jegyzéket egy korábbi projektedhez a Release kimenet fájljaiból.

Egy lehetséges megoldás

Táblázat: fájl, szerep (indító, kód, konfiguráció, függőség, erőforrás, szimbólum), átadni-e, a hiányának következménye. A .pdb és a dokumentációs .xml nem kerül át.

2. Beágyazott erőforrás

Tedd a logo.png képet beágyazott erőforrásba (Resources.resx), és töltsd be onnan. Mi az előny?

Egy lehetséges megoldás

Project → Properties → Resources → kép hozzáadása; Properties.Resources.logo. Előny: nincs külön fájl, amelyet el lehetne veszíteni; hátrány: a kép cseréjéhez újrafordítás kell.

3. Függőség-ellenőrzés

Nézd meg a .deps.json fájlt, és sorold fel, milyen külső könyvtárakat használ a programod.

Egy lehetséges megoldás

A fájl libraries szekciója felsorolja a NuGet csomagokat és projekthivatkozásokat verzióval; mindegyiknek ott kell lennie a kimeneti mappában DLL-ként (vagy a keretrendszer része).

Gyakorlótár: 6 további feladat

Három szinten gyakorolhatsz: alap, közepes és kihívás. Csak a próbálkozás után nyisd le a megoldást.

Alap szint

1. EXE vagy DLL?

Melyik indítható: az .exe vagy a .dll?

Megoldás megnyitása

Az .exe; a .dll kódkönyvtár, amelyet más program tölt be.

2. Mi a solution?

Fogalmazd meg egy mondatban.

Megoldás megnyitása

Egy vagy több projekt gyűjteménye (.sln), amelyet a Visual Studio egyben nyit meg.

Közepes szint

3. A .pdb

Átadod-e a felhasználónak? Miért tartsd meg mégis?

Megoldás megnyitása

Nem kell átadni; magadnak tartsd meg, mert a hibajelentések stack trace-ének sorszámaihoz és a hibakereséshez kell.

4. runtimeconfig.json

Mire való?

Megoldás megnyitása

Megmondja, milyen .NET futtatókörnyezet és verzió kell a program futtatásához.

Kihívás szint

5. BaseDirectory

Miért jobb az AppContext.BaseDirectory a munkakönyvtárnál?

Megoldás megnyitása

Mindig a program mappáját adja, míg a munkakönyvtár az indítás módjától függ (parancsikon, parancssor, fájlválasztó ablak).

6. Írható adat

Hová mentse a program a felhasználó adatait telepítés után?

Megoldás megnyitása

Az ApplicationData (vagy LocalApplicationData) mappába; a program mappájába (Program Files) általában nincs írási jog.

Gyors önellenőrzés

Válaszolj fejben, és csak utána nyisd le a választ.

1. Mi az assembly?

A fordítás eredménye: egy .exe vagy .dll.

2. Miért van .exe és .dll is?

Az exe az indító (apphost), a dll tartalmazza a program kódját.

3. Mi a .deps.json?

A függőségek listája.

4. Mi a Copy to Output Directory?

A fájl a fordításkor a kimeneti mappába másolódik.

5. Mit nem adsz át?

A .pdb és a dokumentációs .xml fájlokat.

6. Mit ad az AppContext.BaseDirectory?

A program saját mappáját.

7. Hol ellenőrzöd az önállóságot?

Tiszta mappában vagy másik gépen, fejlesztői környezet nélkül.

Mit tudsz már?

  • Érted a solution, projekt és assembly viszonyát, valamint az EXE és DLL szerepét.
  • Tudod, mi micsoda a kimeneti mappában, és mit kell átadni.
  • Az adatfájlokat a kimenetbe másolod, és a program mappájából éred el.
  • Tiszta környezetben ellenőrzöd, hogy a program önállóan fut.

Következő lecke: .NET és .NET Framework futtatókörnyezet

Milyen .NET kell a program futtatásához, és mit tegyél, ha a felhasználó gépén nincs.