Grafikus C# – Windows Forms tanfolyam › 14.6 lecke Windows Forms · 14.6 lecke · kiadás A ZIP kényelmes a fejlesztőknek, de a felhasználók többsége telepítőt vár: duplakatt, tovább, tovább, kész: a program megjelenik a Start menüben, van eltávolítása, és újabb verzió esetén egyszerűen frissül. Ebben a leckében megtanulod, mit tud egy telepítő, milyen telepítő-technológiák vannak (Inno Setup, MSI, MSIX, ClickOnce), mi a különbség a felhasználói és a gépszintű telepítés között, hogyan készítesz egyszerű telepítőszkriptet, hogyan működik az eltávolítás, és hogyan frissül a program: új telepítővel, vagy beépített frissítés-ellenőrzővel, amelyet biztonságosan, a felhasználó tudtával kell megvalósítani.Telepítési csomagok és frissítés

A lecke végére
- megmondod, mit nyújt a telepítő a ZIP-hez képest (Start menü, eltávolítás, frissítés);
- ismered a telepítő-technológiákat: Inno Setup, MSI, MSIX, ClickOnce;
- megkülönbözteted a felhasználói és a gépszintű telepítést;
- elkészítesz egy Inno Setup szkriptet, és kipróbálod a telepítést, eltávolítást és frissítést;
- megírsz egy egyszerű, biztonságos frissítés-ellenőrzőt (
HttpClient, verzióösszehasonlítás); - tudod, mit kell eldöntened az eltávolításnál (felhasználói adatok sorsa).
Mielőtt elkezded
Ehhez a leckéhez a 14.1–14.5 lecke szükséges, különösen a 14.5 (Publish) és a 11. fejezet (async).
Mit tud a telepítő, és milyen fajták vannak?
| Technológia | Jellemző | Mikor? |
|---|---|---|
| Inno Setup | Ingyenes, szkript alapú (.iss), egyetlen Setup.exe-t készít; rugalmas, széles körben használt. | Hobbi- és kisprojekt, egyszerű telepítő gyorsan. |
| MSI (WiX Toolset) | A Windows hagyományos telepítőformátuma; XML alapú leírás; csoportházirenddel központilag telepíthető. | Vállalati környezet, rendszergazdai telepítés. |
| MSIX | Modern csomagformátum: tiszta telepítés/eltávolítás, tárolt működés; aláírás szükséges. | Store-terjesztés, modern vállalati telepítés. |
| ClickOnce | Visual Studio beépített varázslója; telepít és automatikusan frissít; felhasználói szintű. | Belső eszköz, egyszerű önfrissítő terjesztés (14.5 lecke). |
| winget / csomagkezelő | Parancssoros telepítés egy központi jegyzékből (winget install Program). | Nyilvános, ismert programok. |
%LocalAppData%\Programs) nem igényel rendszergazdai jogot, és csak az adott felhasználónak szól. A gépszintű (C:\Program Files) rendszergazdai jogot kér, és minden felhasználónak elérhető. Iskolai gépen sokszor csak a felhasználói telepítés lehetséges.Jósolj!
Az iskolai gépeken a diákok nem rendszergazdák. Melyik telepítési módot kell választanod: felhasználói vagy gépszintűt?
Jóslat ellenőrzése
Felhasználói (rendszergazdai jog nélküli): a program a felhasználó saját mappájába települ (%LocalAppData%\Programs). A gépszintű telepítés a Program Files mappába írna, amihez rendszergazdai jelszó kellene.
Telepítő készítése Inno Setuppal
[Setup]
; az AppId ELLENŐRZI, hogy ugyanannak a programnak a frissítéséről van szó: egyszer generáld (Tools → Generate GUID), és ne változtasd!
AppId={{8C3F6B1A-0000-4D2E-9A11-123456789ABC}
AppName=Diáknyilvántartó
AppVersion=1.0.0
AppPublisher=Példa Diák
DefaultDirName={autopf}\Diaknyilvantarto
DefaultGroupName=Diáknyilvántartó
; felhasználói telepítés: nem kér rendszergazdát (a megjegyzés külön sorban áll: a sor végi ; az érték része lenne)
PrivilegesRequired=lowest
; a felhasználó dönthet: csak nekem / minden felhasználónak
PrivilegesRequiredOverridesAllowed=dialog
OutputDir=kiadas
OutputBaseFilename=Diaknyilvantarto-Setup-1.0.0
Compression=lzma2
SolidCompression=yes
WizardStyle=modern
ArchitecturesAllowed=x64compatible
ArchitecturesInstallIn64BitMode=x64compatible
UninstallDisplayIcon={app}\Diaknyilvantarto.exe
[Tasks]
Name: desktopicon; Description: "Parancsikon az Asztalon"; Flags: unchecked
[Files]
; a közzétett (publish) mappa teljes tartalma
Source: "..\publish\onallo\*"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs createallsubdirs
[Icons]
Name: "{group}\Diáknyilvántartó"; Filename: "{app}\Diaknyilvantarto.exe"
Name: "{group}\Eltávolítás"; Filename: "{uninstallexe}"
Name: "{autodesktop}\Diáknyilvántartó"; Filename: "{app}\Diaknyilvantarto.exe"; Tasks: desktopicon
[Run]
Filename: "{app}\Diaknyilvantarto.exe"; Description: "A program indítása"; Flags: nowait postinstall skipifsilent[Setup] az alapadatok (név, verzió, hely), a [Files] a másolandó fájlok (a Publish mappa), az [Icons] a parancsikonok, a [Tasks] a felhasználó által választható extrák, a [Run] a telepítés végén futó lépés. A fordítás: Compile gomb az Inno Setup szerkesztőben (vagy ISCC.exe telepito.iss), az eredmény egy Setup.exe.AppId azonosítja a programot: ugyanazzal az azonosítóval készült újabb telepítő frissítésként a régi helyére települ (a régi fájlokat felülírja), és a Windows listájában egy bejegyzés marad. Ha minden verzióhoz más AppId-t adsz, párhuzamos példányok jönnek létre.{autopf} a telepítés módjától függően a Program Files (gépszintű) vagy a %LocalAppData%\Programs (felhasználói) mappát jelenti: ezért működik mindkét módban. A {app} a kiválasztott telepítési mappa.[Code] szakasz).Jósolj!
Az 1.0.0 verzió telepítője AppId=A. A 1.1.0 verzióhoz véletlenül új GUID-ot (AppId=B) generálsz. Mi történik, ha a felhasználó az újat is telepíti?
Jóslat ellenőrzése
A telepítő külön programként kezeli: két bejegyzés az Alkalmazások és szolgáltatások listában, két mappa (vagy ugyanabba másolva a fájlok összekeverednek), és a régi eltávolítása nem érinti az újat. A frissítéshez az AppId állandó kell legyen.
Frissítés: telepítővel és frissítés-ellenőrzővel
1. Új telepítő
A felhasználó letölti és lefuttatja az új verzió telepítőjét: az azonos AppId miatt a régi helyére települ. A legegyszerűbb, megbízható mód; a felhasználónak tudnia kell az új verzióról.
2. ClickOnce / Store
A platform maga ellenőrzi és telepíti a frissítést. Kényelmes, de a platform szabályaihoz kötött.
3. Frissítés-ellenőrző a programban
A program értesít az új verzióról (egy kis verziófájl lekérdezésével), és a letöltési oldalra irányít. Egyszerű és átlátható; a letöltést és telepítést a felhasználó indítja.
4. Automatikus önfrissítés
A program maga tölti le és cseréli a fájljait. Kényelmes, de veszélyes (aláírás, hash és jogosultság kell hozzá): kezdőként kerüld; inkább ClickOnce vagy telepítő.
public class FrissitesInfo
{
public string Verzio { get; set; }
public string Letoltes { get; set; }
public string Sha256 { get; set; }
public string Valtozasok { get; set; }
}
public static class FrissitesEllenorzo
{
private static readonly HttpClient kliens = new HttpClient { Timeout = TimeSpan.FromSeconds(5) }; // egyetlen példány, időkorláttal
public static async Task<FrissitesInfo> LegujabbAsync(string hely)
{
string json = hely.StartsWith("http", StringComparison.OrdinalIgnoreCase)
? await kliens.GetStringAsync(hely) // éles: egy kis JSON a weboldalról (HTTPS!)
: File.ReadAllText(hely); // teszt: helyi fájl
return JsonSerializer.Deserialize<FrissitesInfo>(json, new JsonSerializerOptions { PropertyNameCaseInsensitive = true });
}
public static bool Ujabb(string jelenlegi, string legujabb)
{
Version a, b;
return Version.TryParse(jelenlegi, out a) && Version.TryParse(legujabb, out b) && b > a; // verzióként, NEM szövegként hasonlítjuk ("1.10" > "1.9")
}
}
// A Formban
private async void btnFrissites_Click(object sender, EventArgs e)
{
btnFrissites.Enabled = false;
try
{
FrissitesInfo info = await FrissitesEllenorzo.LegujabbAsync(frissitesUrl);
string jelenlegi = Application.ProductVersion; // az assembly verziója (14.8 lecke)
if (info != null && FrissitesEllenorzo.Ujabb(jelenlegi, info.Verzio))
{
if (MessageBox.Show(this, "Új verzió érhető el: " + info.Verzio + Environment.NewLine + info.Valtozasok + Environment.NewLine + Environment.NewLine + "Megnyitod a letöltési oldalt?", "Frissítés", MessageBoxButtons.YesNo, MessageBoxIcon.Information) == DialogResult.Yes)
{
Uri uri;
if (Uri.TryCreate(info.Letoltes, UriKind.Absolute, out uri) && uri.Scheme == Uri.UriSchemeHttps) // csak https hivatkozást nyitunk meg
{
Process.Start(new ProcessStartInfo(uri.AbsoluteUri) { UseShellExecute = true });
}
}
}
else { tsslUzenet.Text = "A program naprakész (" + jelenlegi + ")."; }
}
catch (Exception ex) when (ex is HttpRequestException || ex is TaskCanceledException || ex is JsonException || ex is IOException || ex is UriFormatException)
{
tsslUzenet.Text = "A frissítés-ellenőrzés most nem sikerült (nincs kapcsolat?)."; // csendes hiba: a program nem függ az ellenőrzéstől
}
finally { btnFrissites.Enabled = true; }
}{
"verzio": "1.1.0",
"letoltes": "https://pelda.hu/diaknyilvantarto/Diaknyilvantarto-Setup-1.1.0.exe",
"sha256": "3F2A...C91B",
"valtozasok": "Javítva a CSV-betöltés; új Névjegy ablak."
}"1.10.0" kisebb, mint "1.9.0" (betűrend). A System.Version a számokat hasonlítja, ezért helyes. Az Application.ProductVersion néha kiegészítő szöveget (+commit) tartalmaz: ilyenkor a Version.TryParse előtt vágd le.https sémával nyisd meg; a letöltött telepítő hash-ét (a JSON-ból) ellenőrizd, ha automatikusan töltenél; soha ne futtass letöltött kódot a felhasználó megerősítése nélkül.Jósolj!
A frissítés-ellenőrző a verziókat string.Compare(jelenlegi, legujabb) < 0 módon hasonlítja. A jelenlegi verzió 1.9.0, a legújabb 1.10.0. Mit mond a program?
Jóslat ellenőrzése
A szövegként összehasonlított "1.10.0" betűrendben a "1.9.0" előtt áll (az 1 karakter kisebb, mint a 9), ezért a program naprakésznek hiszi magát: a felhasználó sosem értesül az új verzióról. A Version típus a számokat hasonlítja, ezért helyes.
Eltávolítás és a felhasználói adatok
%AppData% mappában) nem ismeri, ezért alapból ott marad.[UninstallDelete] szakasza adott fájlokat/mappákat töröl eltávolításkor (például Type: filesandordirs; Name: "{localappdata}\Diaknyilvantarto\naplo"). Felhasználói adatot csak a felhasználó jóváhagyásával törölj.Jósolj!
A felhasználó eltávolítja a programot, és fél év múlva újra telepíti. A jegyzetei eltűntek. Mi lehetett a hiba?
Jóslat ellenőrzése
Az eltávolító törölte a felhasználói adatokat (vagy az adatok a program mappájában voltak, és azzal együtt törlődtek). A felhasználói adat az %AppData% mappában legyen (13.6, 14.7 lecke), és az eltávolítás ne törölje, vagy előbb kérdezzen.
Mit tegyél ide: a telepítő varázslója és az Alkalmazások és szolgáltatások listában a program bejegyzése.Javasolt fájlnév: winforms-14-6-telepito.webp · Alt szöveg: A telepítő és az eltávolítási bejegyzés
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 frissítés után két program van a listán
Az Alkalmazások és szolgáltatások két bejegyzést mutat. Az új telepítő más Ok és javítás
AppId-t kapott. Az AppId egy programhoz örökre ugyanaz; a duplikátumot távolítsd el.
2. A telepítő a Program Files-ba ír, és hibával leáll
Iskolai gépen az „Access denied” jön. Gépszintű telepítés nem rendszergazdának. Ok és javítás
PrivilegesRequired=lowest és {autopf}: felhasználói telepítés.
3. Az új verzió nem jelenik meg
A frissítés-ellenőrző szerint a program naprakész, pedig van újabb. Szöveges verzióösszehasonlítás (Ok és javítás
"1.10" < "1.9"), vagy a JSON régi (gyorsítótár). Version típus, és ellenőrizd a szerveren lévő JSON-t.
4. A program lefagy a frissítés-ellenőrzéskor
Hálózat nélkül az ablak másodpercekig nem reagál. Szinkron lekérdezés a felületi szálon, vagy nincs időkorlát. Ok és javítás
await és HttpClient.Timeout; a hibát csendben kezeld (11. fejezet, 13.6 lecke).
5. Az eltávolítás után maradt mappa
A program mappája nem tűnt el teljesen. A program (vagy egy bővítmény) fájlokat hozott létre a telepítés után a saját mappájában. A telepítő ezeket nem ismeri: Ok és javítás
[UninstallDelete], vagy a futásidejű adatot az %AppData% mappába tedd.
6. A felhasználó nem bízik a frissítésben
Az értesítés minden indításkor megjelenik, és idegesítő. Adj beállítást (ki/be, „később”, „ezt a verziót kihagyom”), és ne ellenőrizz minden indításkor, hanem naponta egyszer; a felhasználó döntsön.Ok és javítás
Mini projekt: telepítő és frissítés-ellenőrző
Készíts telepítőt a programodhoz, próbáld ki a telepítést, a frissítést és az eltávolítást, és építs be frissítés-ellenőrzőt:
- Előkészítés: a 14.5 lecke szerint készíts önálló csomagot (
publish\onallo) az 1.0.0 verzióról (a verzió beállítását a 14.8 lecke részletezi: itt a-p:Version=1.0.0elég). - Inno Setup: telepítsd az Inno Setup-ot (jrsoftware.org), és készítsd el a
telepito.issszkriptet a leckéből (sajátAppIdGUID-dal: Tools → Generate GUID). - Fordítás: fordítsd a szkriptet; az eredmény a
kiadas\Diaknyilvantarto-Setup-1.0.0.exe. - Telepítés: telepítsd felhasználói módon (nem rendszergazdaként); ellenőrizd: Start menü, Asztal parancsikon (ha kérted), az Alkalmazások és szolgáltatások bejegyzése.
- Adat létrehozása: használd a programot úgy, hogy keletkezzen felhasználói adat az
%AppData%mappában. - Frissítés: készíts 1.1.0 verziót (kis módosítás: például a Névjegy szövege), új telepítővel (azonos AppId,
AppVersion=1.1.0); telepítsd a régi fölé; ellenőrizd, hogy egy bejegyzés van, a verzió 1.1.0, az adat megmaradt. - Frissítés-ellenőrző: építsd be a
FrissitesEllenorzoosztályt; afrissitesUrlegy helyilegujabb.jsonfájl (próbához), amelyben a verzió1.1.0; az 1.0.0 programnak jeleznie kell az újat, az 1.1.0-nak nem. Próbáld hibás JSON-nal, nem létező fájllal, nagyon lassú hálózattal (kikapcsolt hálózat): a program ne omoljon össze. - Eltávolítás: távolítsd el az Alkalmazások és szolgáltatások listából; ellenőrizd, mi maradt a program mappájában és az
%AppData%mappában; döntsd el és dokumentáld, hogy a felhasználói adat marad-e. - Jegyzet: írd le a telepítési útmutatót (követelmények, felhasználói/gépszintű módszer, SmartScreen, frissítés, eltávolítás, adatok helye).
Megoldás megnyitása (próbáld ki előbb önállóan!)
// A frissítés-ellenőrző kapcsolása és a beállítás (ki/be)
private string frissitesUrl = System.IO.Path.Combine(AppContext.BaseDirectory, "legujabb.json"); // próbához: helyi fájl; élesben HTTPS cím
private async void Form1_Shown(object sender, EventArgs e)
{
if (!Properties.Settings.Default.FrissitesEllenorzes) { return; } // a felhasználó kikapcsolhatja (14.7 lecke)
await Ellenoriz(csendes: true); // induláskor csendben: csak az új verzió esetén jelez
}
private async System.Threading.Tasks.Task Ellenoriz(bool csendes)
{
try
{
FrissitesInfo info = await FrissitesEllenorzo.LegujabbAsync(frissitesUrl);
if (info != null && FrissitesEllenorzo.Ujabb(Application.ProductVersion.Split('+')[0], info.Verzio))
{
tsslUzenet.Text = "Új verzió érhető el: " + info.Verzio;
}
else if (!csendes) { tsslUzenet.Text = "A program naprakész."; }
}
catch (Exception ex) when (ex is System.Net.Http.HttpRequestException || ex is System.Threading.Tasks.TaskCanceledException || ex is System.Text.Json.JsonException || ex is System.IO.IOException)
{
if (!csendes) { tsslUzenet.Text = "A frissítés-ellenőrzés nem sikerült."; }
}
}
// legujabb.json (a program mellé másolva a kimenetbe: CopyToOutputDirectory)
// { "verzio": "1.1.0", "letoltes": "https://pelda.hu/Diaknyilvantarto-Setup-1.1.0.exe", "sha256": "", "valtozasok": "Új Névjegy ablak" }Várt tapasztalat: az 1.0.0 program az újabb JSON miatt jelzi az 1.1.0-t; telepítés után az 1.1.0 már nem jelez; az azonos AppId miatt egyetlen bejegyzés marad; a felhasználói adat az %AppData% mappában az eltávolítás után is megvan (kivéve, ha a szkriptben törlést kértél). A beállítás (Settings) használatát a 14.7 lecke részletezi; addig használhatsz egy egyszerű bool mezőt.
Mit tegyél ide: a telepítés előtti és utáni Alkalmazások-lista, és az „Új verzió érhető el” üzenet.Javasolt fájlnév: winforms-14-6-kesz.webp · Alt szöveg: A telepítő és a frissítés-ellenőrző
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. Futtatókörnyezet-ellenőrzés
Keretrendszer-függő csomagnál hogyan figyelmeztetné a telepítő a hiányzó Desktop Runtime-ot? Az Inno Setup Egy lehetséges megoldás
[Code] szakaszában a telepített futtatókörnyezetek ellenőrzése (a rendszerleíró adatbázisból vagy a dotnet --list-runtimes kimenetéből), és ha hiányzik, üzenet a letöltési hivatkozással, vagy a futtatókörnyezet telepítője csendes módban a telepítés előtt. Egyszerűbb: önálló csomag.
2. Csendes telepítés
Hogyan telepítenéd a programot felügyelet nélkül, több gépre? Az Inno Setup kapcsolói: Egy lehetséges megoldás
Setup.exe /VERYSILENT /SUPPRESSMSGBOXES /DIR="C:\Programok\Diak"; a gépszintű telepítéshez /ALLUSERS és rendszergazdai jog. Az eltávolítás unins000.exe /VERYSILENT.
3. Kihagyom ezt a verziót
Bővítsd a frissítés-ellenőrzőt: a felhasználó kihagyhat egy verziót. A beállításba (Egy lehetséges megoldás
Settings) mentsd a kihagyott verziót; az értesítés csak a nála újabbnál jelenik meg. Az Új verzió ablakban Később és Kihagyom gomb.
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. Telepítő vagy ZIP?
Mikor jobb a telepítő? Ha Start menü, eltávolítás és egyszerű frissítés kell; a ZIP hordozható használatra vagy kis eszközökhöz jó.Megoldás megnyitása
2. AppId
Mire jó az Azonosítja a programot: azonos azonosítóval készült új telepítő frissítésként a régi helyére települ.AppId?Megoldás megnyitása
Közepes szint
3. Felhasználói telepítés
Mit jelent a A telepítő nem kér rendszergazdai jogot: a program a felhasználó saját mappájába települ.PrivilegesRequired=lowest?Megoldás megnyitása
4. Verzió-összehasonlítás
Miért A szöveges összehasonlítás betűrend szerint dönt: Version, és nem string?Megoldás megnyitása
"1.10" < "1.9"; a Version a számokat hasonlítja.
Kihívás szint
5. Biztonság
Miért veszélyes az automatikus önfrissítés? Ha a forrást feltörik vagy a kapcsolat nem biztonságos, a program kártékony kódot tölthet le és futtathat; aláírás, hash és megbízható csatorna nélkül nem szabad.Megoldás megnyitása
6. Adat az eltávolításkor
Mit teszel a felhasználói adattal? Alapból megtartod (az Megoldás megnyitása
%AppData% mappában), vagy rákérdezel; a naplókat és gyorsítótárat törölheted.
Gyors önellenőrzés
Válaszolj fejben, és csak utána nyisd le a választ. Fájlok elhelyezése, parancsikonok, eltávolítás, frissítés kezelése. Inno Setup, MSI, MSIX, ClickOnce, csomagkezelők (winget). Felhasználói: nem kell rendszergazda; gépszintű: Program Files, minden felhasználónak. Új telepítővel (azonos AppId), ClickOnce/Store-ral, vagy frissítés-ellenőrzővel értesítve. HTTPS, időkorlát, csendes hibakezelés, https-hivatkozás megnyitása, felhasználói döntés, nincs személyes adat. Az Telepítés, használat, frissítés régi fölé, eltávolítás, újratelepítés.1. Mit nyújt a telepítő?
2. Milyen telepítő-technológiák vannak?
3. Mi a különbség a telepítési módok közt?
4. Hogyan frissül a program?
5. Mi a biztonságos frissítés-ellenőrzés?
6. Hová kerül a felhasználói adat?
%AppData% mappába, nem a program mappájába.7. Mit tesztelsz telepítőnél?
Mit tudsz már?
- Telepítőt készítesz (Inno Setup), és ismered a többi technológiát is.
- Megkülönbözteted a felhasználói és a gépszintű telepítést, és érted az AppId szerepét.
- Biztonságos frissítés-ellenőrzőt építesz verzióösszehasonlítással.
- Kezeled az eltávolítást és a felhasználói adat sorsát.
Következő lecke: Fájlok, adatbázisok helye telepítés után
Hová kerüljenek a beállítások, adatok és naplók telepítés után, és hogyan kezeld a jogosultságokat.



