Grafikus C# – Windows Forms tanfolyam › 14.4 lecke Windows Forms · 14.4 lecke · build Nem kell mindent magadnak megírnod: a CSV-olvasót, a naplózót, az adatbázis-meghajtót mások már megírták és kipróbálták. Ezeket NuGet-csomagként építheted be a programodba, néhány kattintással. De minden külső könyvtár egyben függőség is: a program csak akkor fut, ha az a könyvtár ott van a kimeneti mappában, a verziója megfelelő, a licence engedi a használatot, és biztonsági hibája nincs. Ebben a leckében megtanulod a csomagok hozzáadását és kezelését (NuGet-függőségek
PackageReference), a verziók és a tranzitív függőségek működését, azt, hogy a csomagok fájljai hogyan kerülnek a kimenetbe (a natív DLL-ekkel együtt), hogyan választasz megbízható csomagot, és hogyan frissítesz biztonságosan.
A lecke végére
- csomagot adsz a projekthez (Visual Studio és
dotnet add package), és érted aPackageReference-t; - ismered a verziószámozást (major.minor.patch) és a tranzitív függőséget;
- tudod, hogyan kerülnek a csomag DLL-jei és natív fájljai a kimenetbe;
- a csomagot több szempont szerint választod (karbantartás, licenc, biztonság, méret);
- listázod és frissíted a csomagokat (
dotnet list package --outdated); - kezeled a tipikus NuGet-hibákat (restore, verzióütközés, natív könyvtár).
Mielőtt elkezded
Ehhez a leckéhez a 14.2–14.3 lecke szükséges. A 13.6 lecke SQLite-példája már használt NuGet-csomagot (Microsoft.Data.Sqlite).
Csomag hozzáadása és a PackageReference
Visual Studio: Jobb klikk a projekten → Manage NuGet Packages... → Browse → keresés → Install
Parancssor: dotnet add package Microsoft.Data.Sqlite
dotnet add package CsvHelper --version 33.0.1
dotnet remove package CsvHelper
dotnet restore (a csomagok letöltése a .csproj alapján)
dotnet list package (a használt csomagok és verziók)
dotnet list package --outdated (az elavultak)
dotnet list package --vulnerable (ismert biztonsági hibával)
dotnet list package --include-transitive (a közvetett függőségekkel együtt)<ItemGroup>
<PackageReference Include="Microsoft.Data.Sqlite" Version="8.0.0" />
<PackageReference Include="CsvHelper" Version="33.0.1" />
</ItemGroup>dotnet restore (vagy a Visual Studio fordításkor) letölti a csomagot a gép közös gyorsítótárába (%UserProfile%\.nuget\packages), és onnan kerül a kimenetbe. A csomag fájljait nem tárolod a projektben és a verziókezelésben.--include-transitive). Így egy csomag hozzáadása több DLL-t is jelenthet.Jósolj!
Egy barátod megkapja a projekted mappáját (a bin és obj nélkül), megnyitja, és fordítja. A CsvHelper DLL nincs a mappában. Lefordul-e?
Jóslat ellenőrzése
Igen (ha van internet): a Visual Studio vagy a dotnet restore a .csproj PackageReference sora alapján letölti a csomagot (package restore). Offline gépen a fordítás NU1101/NU1301 hibával áll meg, kivéve, ha a csomag a gép gyorsítótárában már megvan.
Mi kerül a kimenetbe?
Konyvtar.App.exe, Konyvtar.App.dll, .runtimeconfig.json, .deps.json ← a program
CsvHelper.dll ← NuGet-csomag (kezelt kód)
Microsoft.Data.Sqlite.dll ← NuGet-csomag
SQLitePCLRaw.core.dll, SQLitePCLRaw.provider... ← tranzitív függőségek
runtimes\
win-x64\native\e_sqlite3.dll ← NATÍV könyvtár (nem .NET kód!), architektúránként
win-x86\native\e_sqlite3.dll
linux-x64\native\libe_sqlite3.so ← más platformokhoz (Windowson nem kell)runtimes\<platform>\native mappában. A natív DLL-nek a program platformjához kell illeszkednie (x64/x86): hibás platformnál DllNotFoundException/BadImageFormatException.runtimes mappa a program része: az átadandó mappából nem hiányozhat (14.2 lecke). A Publish (14.5 lecke) ezt a megfelelő, egy platformra szűrt tartalommal gyűjti össze..deps.json felsorolja a csomagokat és a natív fájlokat: a futtatókörnyezet ebből tudja, mit hol keressen. Ne töröld, és ne szerkeszd kézzel.Jósolj!
A programodat 64 bites gépen fejlesztetted, és az átadott mappában csak a win-x86\native\e_sqlite3.dll van (a win-x64 mappát kihagyták). Mi történik az SQLite használatakor 64 bites gépen?
Jóslat ellenőrzése
A program a 64 bites folyamatban a 64 bites natív könyvtárat keresi, nem találja: DllNotFoundException (vagy Unable to load DLL 'e_sqlite3') hibával elszáll az első adatbázis-használatkor. Ezért kell a teljes runtimes mappa (vagy a Publish).
Hogyan válassz csomagot?
| Szempont | Mit nézz? |
|---|---|
| Szükséges-e? | Nincs-e a keretrendszerben már (System.Text.Json, System.IO, HttpClient)? Egy kis feladathoz írj saját kódot. |
| Karbantartás | Mikor volt az utolsó kiadás? Aktív-e a fejlesztő? Hány megoldatlan hiba van? |
| Népszerűség és hírnév | Letöltések száma, ismert szervezet (Microsoft, .NET Foundation), dokumentáció. |
| Licenc | MIT, Apache 2.0, BSD: általában szabadon használható. GPL: másolt vagy terjesztett programra kötelezettség. Kereskedelmi/saját licenc: ellenőrizd a feltételeket. A licenc a NuGet-oldalon és a csomagban van. |
| Biztonság | Ismert sebezhetőség (dotnet list package --vulnerable, a NuGet-oldal figyelmeztetése). |
| Függőségek | Hány további csomagot hoz? Natív kódot tartalmaz-e (platformfüggés)? |
| Kompatibilitás | Támogatja-e a cél-keretrendszeredet (net8.0, netstandard2.0)? Az NU1701 figyelmeztetés régebbi, nem teljesen kompatibilis csomagra utal. |
--vulnerable).Jósolj!
Egy csomag utolsó kiadása 6 éve volt, 40 megoldatlan hibabejelentéssel, és egy ismert biztonsági figyelmeztetéssel. Mégis ez tudja pontosan azt, amire szükséged van. Mit teszel?
Jóslat ellenőrzése
Keress alternatívát (karbantartott csomag vagy keretrendszeri megoldás), vagy írd meg a szükséges részt magad. Egy elhagyott, sebezhető csomag hosszú távon kockázat: a hibákat senki sem javítja, és minden felhasználód viseli a következményt.
Frissítés és verziókezelés
Biztonságos frissítés lépései
- Listázd:
dotnet list package --outdatedés--vulnerable. - Olvasd el a kiadási jegyzetet (release notes, breaking changes), főleg major váltásnál.
- Frissíts egyet egyszerre (
dotnet add package X --version Y). - Fordítsd le, nézd a figyelmeztetéseket (Error List).
- Futtasd a teszteket (13.8 lecke): regressziós készlet.
- Naplózd a változást (melyik csomag, melyik verzióról melyikre, miért).
Szabályok
- A biztonsági frissítés (sebezhetőség) sürgős: ne halogasd.
- Kiadás előtt ne frissíts mindent: új hibát hozhat. Előbb a teszteléssel ellenőrizd.
- Rögzített verzió: a
Version="33.0.1"pontos; a lebegő verzió (33.*) kiszámíthatatlan. - Vedd ki a nem használt csomagot (
dotnet remove package). - Licencjegyzék: tartsd naprakészen, mely csomag mely licenccel van a programban.
- Reprodukálható build: a
packages.lock.json(RestorePackagesWithLockFile) rögzíti a pontos verziókat, a tranzitívakat is.
NU1605 hiba (a downgrade). Megoldás: a közös csomag verzióját közvetlenül add meg a projektben a megfelelő szinten.Jósolj!
A CsvHelper verzióját 33.0.1-ről 34.0.0-ra emeled (major váltás), és a fordítás hibátlan. Elég-e ennyi ellenőrzés?
Jóslat ellenőrzése
Nem: a fordítás csak a nyelvi kompatibilitást ellenőrzi. A major verzió viselkedése is változhat (alapértelmezett beállítások, kerekítés, elválasztó), ezért a programot futtatni és tesztelni kell (13.8 lecke), és el kell olvasni a változásjegyzéket.
Mit tegyél ide: a NuGet csomagkezelő ablak (telepített csomagok, frissítések) és a dotnet list package kimenete.Javasolt fájlnév: winforms-14-4-nuget.webp · Alt szöveg: A NuGet csomagkezelő
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. NU1101: nem található a csomag
A fordítás a csomag letöltésénél áll meg. Elírt csomagnév, nincs internet, vagy a csomagforrás nem elérhető. Ellenőrizd a nevet és a forrást (Tools → NuGet Package Manager → Package Sources).Ok és javítás
2. NU1605: csomag-visszalépés
A hiba szerint egy csomagot alacsonyabb verzióra „frissítene”. Verzióütközés: add meg a közvetlenül használt csomagot a magasabb verzióval a Ok és javítás
.csproj-ban.
3. Fordul, de futáskor FileNotFoundException
A másik gépen a csomag DLL-je hiányzik. Az átadott mappából kimaradt egy DLL (14.2 lecke). Adj át teljes kimenetet vagy Publish csomagot (14.5 lecke).Ok és javítás
4. DllNotFoundException az adatbázisnál
A program SQLite-hívásnál elszáll a másik gépen. A natív könyvtár (Ok és javítás
runtimes\win-x64\native) hiányzik, vagy a platform nem egyezik. Ellenőrizd a runtimes mappát és a platformcélt (14.1 lecke).
5. NU1903: ismert sebezhetőség
A fordítás figyelmeztetést ad egy csomagra. A csomag (vagy egy tranzitív függősége) sebezhető. Frissítsd a javított verzióra (Ok és javítás
--include-transitive segít megtalálni), majd teszteld.
6. A frissítés után másképp működik
A csomag frissítése után a CSV kimenet formátuma megváltozott. A major váltás viselkedést változtatott. Olvasd el a változásjegyzéket, állítsd be a megfelelő konfigurációt (például elválasztó), vagy rögzítsd a régi verziót, amíg a kódot nem igazítod. A regressziós teszt (13.8 lecke) ezt kapta volna el.Ok és javítás
Mini projekt: függőség-audit
Készíts egy kis programot két NuGet-csomaggal, majd végezz függőség-auditot: mit hoz a két csomag, mi kerül a kimenetbe, milyen licencek és biztonsági állapot tartozik hozzájuk:
- Projekt: Windows Forms (
Audit);btnExport(Lista exportja CSV-be),btnDb(Mentés SQLite-ba),lstBetoltott(betöltött assembly-k),lblUzenet. - Csomagok: add hozzá a
CsvHelperés aMicrosoft.Data.Sqlitecsomagot (Visual Studio vagydotnet add package); jegyezd fel a telepített verziókat. - Kód: másold be a lenti kódot (CSV-export és SQLite-mentés, a betöltött assembly-k listázása).
- Parancsok: futtasd a
dotnet list package,dotnet list package --include-transitive,--outdatedés--vulnerableparancsot; írd le a kimenetet. - Kimenet: fordítsd Release módban, és jegyezd fel a
bin\Releasemappa DLL-jeit és aruntimesmappa tartalmát; melyik a kezelt, melyik a natív? - Tiszta restore: töröld a
binésobjmappát, majd futtasd adotnet restoreésdotnet build -c Releaseparancsot; a csomagok újra letöltődnek-e? - Licenc-tábla: minden közvetlen csomagnál (a NuGet-oldalról): név, verzió, licenc, utolsó kiadás, függőségek száma, natív?, szükséges-e valóban?.
- Frissítés próba: frissíts egy csomagot egy újabb patch vagy minor verzióra, fordíts, és futtasd a funkciót (CSV, SQLite); jegyezd fel az eredményt, és állítsd vissza, ha hibás.
- Alternatíva: írd le, hogyan oldanád meg a CSV-exportot csomag nélkül (egyszerű
StringBuilder), és mikor érné meg inkább a csomag.
Megoldás megnyitása (próbáld ki előbb önállóan!)
public class Termek { public int Id { get; set; } public string Nev { get; set; } public decimal Ar { get; set; } }
private readonly List<Termek> lista = new List<Termek>
{
new Termek { Id = 1, Nev = "Alma", Ar = 120.5m },
new Termek { Id = 2, Nev = "Körte, érett", Ar = 200m } // a vessző a CsvHelper idézi: nem rontja el a CSV-t
};
private void Form1_Load(object sender, EventArgs e)
{
foreach (var a in AppDomain.CurrentDomain.GetAssemblies().OrderBy(x => x.GetName().Name))
{
lstBetoltott.Items.Add(a.GetName().Name + " " + a.GetName().Version);
}
}
private void btnExport_Click(object sender, EventArgs e)
{
string ut = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments), "termekek.csv");
try
{
using (StreamWriter w = new StreamWriter(ut, false, new System.Text.UTF8Encoding(true)))
using (CsvWriter csv = new CsvWriter(w, CultureInfo.InvariantCulture))
{
csv.WriteRecords(lista);
}
lblUzenet.Text = "CSV mentve: " + ut;
}
catch (Exception ex) when (ex is IOException || ex is UnauthorizedAccessException) { lblUzenet.Text = "A mentés nem sikerült: " + ex.Message; }
}
private void btnDb_Click(object sender, EventArgs e)
{
string db = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "Audit", "termekek.db");
try
{
Directory.CreateDirectory(Path.GetDirectoryName(db));
using (SqliteConnection kap = new SqliteConnection("Data Source=" + db))
{
kap.Open();
using (SqliteCommand c = kap.CreateCommand())
{
c.CommandText = "CREATE TABLE IF NOT EXISTS termek (id INTEGER PRIMARY KEY, nev TEXT, ar REAL)";
c.ExecuteNonQuery();
}
foreach (Termek t in lista)
{
using (SqliteCommand c = kap.CreateCommand())
{
c.CommandText = "INSERT OR REPLACE INTO termek (id, nev, ar) VALUES ($i, $n, $a)";
c.Parameters.AddWithValue("$i", t.Id);
c.Parameters.AddWithValue("$n", t.Nev);
c.Parameters.AddWithValue("$a", (double)t.Ar);
c.ExecuteNonQuery();
}
}
}
lblUzenet.Text = "Adatbázis mentve: " + db;
}
catch (SqliteException ex) { lblUzenet.Text = "Adatbázis-hiba: " + ex.Message; }
catch (Exception ex) when (ex is IOException || ex is UnauthorizedAccessException) { lblUzenet.Text = "Fájlhiba: " + ex.Message; }
}Várható megfigyelések: a CsvHelper.dll és a Microsoft.Data.Sqlite.dll mellett a tranzitív SQLitePCLRaw.* DLL-ek és a runtimes\win-*\native\e_sqlite3.dll kerül a kimenetbe. A csomagok licencei és verziói a NuGet-oldalon olvashatók (a leckében szándékosan nincsenek rögzített számok, mert a csomagok változnak); a saját táblázatodat a valós, aktuális adatokkal töltsd ki. Az alternatíva: kis, egyszerű CSV-nél a StringBuilder és a mezők kézi idézése elég, de a vesszős és idézőjeles szöveg kezelése hibalehetőség; a csomag megéri.
Mit tegyél ide: a függőség-audit táblázata és a dotnet list package --include-transitive kimenete.Javasolt fájlnév: winforms-14-4-kesz.webp · Alt szöveg: A függőség-audit eredménye
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. Harmadik fél licencei
Készíts Minden csomagnál: név, verzió, szerző, licenc neve, a licenc teljes szövege (a NuGet-oldalon vagy a csomagban). A fájl a program mellé kerül (a kimenetbe másolva, 14.2 lecke), és a Névjegy ablakból elérhető (14.8 lecke).THIRD-PARTY-NOTICES.txt fájlt a programod csomagjaihoz.Egy lehetséges megoldás
2. Lock fájl
Kapcsold be a A packages.lock.json használatát, és figyeld meg, mi változik.Egy lehetséges megoldás
.csproj-ban <RestorePackagesWithLockFile>true</RestorePackagesWithLockFile>; a restore létrehozza a fájlt (minden csomag pontos verziójával, a tranzitívakkal együtt). A fájl a forráskódba kerül; dotnet restore --locked-mode hibát jelez, ha a verziók eltérnek.
3. Elavult csomagok
Futtasd a Sürgős: a sebezhetőségi figyelmeztetéssel jelölt csomagok. Később, teszteléssel: a major frissítések (breaking change). Rutinszerűen: patch és minor, regressziós teszt után.dotnet list package --outdated parancsot egy régi projekten, és döntsd el: mit frissítesz azonnal, mit később?Egy lehetséges megoldás
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. Mi a NuGet?
Fogalmazd meg egy mondatban. A .NET csomagkezelője: kész könyvtárakat adhatsz a projekthez verzióval együtt.Megoldás megnyitása
2. Hol a csomag?
Mit tárol a A csomag nevét és verzióját (.csproj?Megoldás megnyitása
PackageReference), nem a DLL-t; a restore tölti le.
Közepes szint
3. Tranzitív
Mi a tranzitív függőség? A csomag saját függősége, amely automatikusan a projektedbe kerül.Megoldás megnyitása
4. SemVer
Melyik verzióváltás lehet törő: 1.2.3 → 1.2.4, 1.2.3 → 1.3.0, vagy 1.2.3 → 2.0.0? A major váltás (2.0.0): kompatibilitást törhet; a patch és a minor általában biztonságos.Megoldás megnyitása
Kihívás szint
5. Natív könyvtár
Miért okozhat gondot a natív könyvtár? Platformfüggő (x64/x86): ha nem illeszkedik, Megoldás megnyitása
DllNotFoundException vagy BadImageFormatException keletkezik.
6. Mikor ne csomag?
Mikor jobb saját kód? Ha a feladat kicsi, és a keretrendszerben megvan; mert minden csomag méretet, biztonsági és karbantartási terhet jelent.Megoldás megnyitása
Gyors önellenőrzés
Válaszolj fejben, és csak utána nyisd le a választ. A projektfájl sora, amely a csomag nevét és verzióját rögzíti. Letölti a Hasonló nevű, rosszindulatú csomag: ezért pontos névvel és ismert forrásból tölts. Az ismert biztonsági hibával jelölt csomagokat. A platformspecifikus (natív) könyvtárak helye a kimenetben. Hogy a feltételek (szerzői jogi nyilatkozat, GPL kötelezettség) betarthatók-e a programod terjesztésekor. Egyet egyszerre, a változásjegyzék elolvasásával, fordítással és regressziós teszttel.1. Mi a PackageReference?
2. Mit tesz a dotnet restore?
.csproj szerinti csomagokat.3. Mi a typosquatting?
4. Mit mutat a --vulnerable?
5. Mi a runtimes mappa?
6. Mire kell figyelni licencnél?
7. Hogyan frissítesz biztonságosan?
Mit tudsz már?
- Csomagot adsz a projekthez, és érted a
PackageReference, a verziók és a tranzitív függőségek működését. - Tudod, mi kerül a kimenetbe (kezelt és natív fájlok).
- Szempontok szerint választasz csomagot (karbantartás, licenc, biztonság).
- Biztonságosan frissítesz, és auditálod a függőségeket.
Következő lecke: Publish és terjesztési lehetőségek
A kész program csomagba rendezése: közzétételi profilok, egyetlen fájl, önálló és keretrendszer-függő módok.



