Útmutató: Előrehaladás lekérése a .NET-keretrendszer 4.5 telepítőjéből
A .NET-keretrendszer 4.5 egy terjeszthető futtatókörnyezet. Ha a .NET-keretrendszer ezen verziójához fejleszt alkalmazásokat, az alkalmazás beállításának előfeltételeként a 4.5-ös .NET-keretrendszer (lánc) beállítását is belefoglalhatja. Testre szabott vagy egységes beállítási felület bemutatásához érdemes lehet csendesen elindítani .NET-keretrendszer 4.5-ös telepítőt, és nyomon követni annak előrehaladását, miközben megjeleníti az alkalmazás beállításának előrehaladását. A csendes nyomkövetés engedélyezéséhez .NET-keretrendszer 4.5-ös beállítás (amely megtekinthető) meghatároz egy protokollt egy memórialeképezett I/O (MMIO) szegmens használatával a beállítással (a figyelővel vagy a láncolóval) való kommunikációhoz. Ez a protokoll határozza meg a láncoló számára a folyamatinformációk beszerzésének, a részletes eredmények lekérésének, az üzenetekre való válaszadásnak és a .NET-keretrendszer 4.5 beállítás megszakításának módját.
Meghívás. A .NET-keretrendszer 4.5 beállításának meghívásához és az MMIO szakasz állapotinformációinak fogadásához a telepítőprogramnak a következőket kell tennie:
Hívja meg a .NET-keretrendszer 4.5 terjeszthető programot:
dotNetFx45_Full_x86_x64.exe /q /norestart /pipe section-name
Ahol a szakasznév bármely olyan név, amelyet az alkalmazás azonosításához használni szeretne. .NET-keretrendszer beállítás aszinkron módon olvassa és írja az MMIO szakaszt, így az adott időszakban kényelmesen használhat eseményeket és üzeneteket. A példában a .NET-keretrendszer beállítási folyamatot egy konstruktor hozza létre, amely mindkettő lefoglalja az MMIO szakaszt (
TheSectionName
) és meghatároz egy eseményt (TheEventName
):Server():ChainerSample::MmioChainer(L"TheSectionName", L"TheEventName")
Cserélje le ezeket a neveket olyan nevekre, amelyek egyediek a telepítőprogramban.
Olvasás az MMIO szakaszból. A .NET-keretrendszer 4.5-ben a letöltési és telepítési műveletek egyidejűek: A .NET-keretrendszer egyik része telepíthető, míg a másik rész letöltése folyamatban van. Ennek eredményeképpen a rendszer visszaküldi az előrehaladást (azaz írott) az MMIO szakaszba két számként (
m_downloadSoFar
ésm_installSoFar
) amely 0-ról 255-re nő. Amikor a 255 meg van írva, és a .NET-keretrendszer kilép, a telepítés befejeződött.
Kilépési kódok. A .NET-keretrendszer 4.5 terjeszthető program meghívásához a következő kilépési kódok jelzik, hogy a telepítés sikeres vagy sikertelen volt-e:
0 – A telepítés sikeresen befejeződött.
3010 – A telepítés sikeresen befejeződött; rendszer újraindítására van szükség.
1602 – A telepítés megszakadt.
Minden más kód – A telepítő hibákat észlelt; a részletekért tekintse át a(z) %temp% fájlban létrehozott naplófájlokat.
A beállítás megszakítása. A telepítést bármikor megszakíthatja az
Abort
MMIO szakaszban található beállítások ésm_ installAbort
jelzők beállításáhozm_downloadAbort
a metódus használatával.
Láncoló minta
A Chainer-minta csendesen elindítja és nyomon követi .NET-keretrendszer 4.5-ös beállítását, miközben megjeleníti az előrehaladást. Ez a minta hasonló a 4. .NET-keretrendszer-hez megadott Chainer-mintához. Emellett azonban elkerülheti a rendszer újraindítását az üzenetmező feldolgozásával .NET-keretrendszer 4 alkalmazás bezárásához. Erről az üzenetmezőről további információt a rendszer újraindításának csökkentése .NET-keretrendszer 4.5-ös telepítések során című témakörben talál. Ezt a mintát a .NET-keretrendszer 4 telepítővel használhatja; ebben a forgatókönyvben a rendszer egyszerűen nem küldi el az üzenetet.
Figyelmeztetés
A példát rendszergazdaként kell futtatnia.
A következő szakaszok a minta jelentős fájljait ismertetik: MMIOChainer.h, ChainingdotNet4.cpp és IProgressObserver.h.
MMIOChainer.h
Az MMIOChainer.h fájl tartalmazza az adatstruktúra definícióját és azt az alaposztályt, amelyből a láncolóosztályt le kell származtatni. A .NET-keretrendszer 4.5 kiterjeszti az MMIO-adatstruktúrát az .NET-keretrendszer 4.5-ös telepítő által igényelt adatok kezelésére. Az MMIO-struktúra módosításai visszamenőlegesen kompatibilisek, így egy .NET-keretrendszer 4 láncoló újrafordítás nélkül képes működni .NET-keretrendszer 4.5-ös beállítással. Ez a forgatókönyv azonban nem támogatja a rendszer újraindításának csökkentésére szolgáló funkciót.
A verziómezők segítségével azonosíthatja a struktúra és az üzenetformátum korrektúráit. A .NET-keretrendszer beállítás a láncoló felületének verzióját határozza meg a
VirtualQuery
függvény meghívásával a fájlleképezés méretének meghatározásához. Ha a méret elég nagy a verziómező elhelyezéséhez, .NET-keretrendszer beállítás a megadott értéket használja. Ha a fájlleképezés túl kicsi ahhoz, hogy verziómezőt tartalmazzon, ami a .NET-keretrendszer 4 esetében van így, a beállítási folyamat a 0-s verziót (4) feltételezi. Ha a láncoló nem támogatja annak az üzenetnek a verzióját, amelyet .NET-keretrendszer telepítő küldeni szeretne, .NET-keretrendszer beállítás figyelmen kívül hagyja a választ.Az MMIO-adatstruktúra a következőképpen van definiálva:
// MMIO data structure for interprocess communication struct MmioDataStructure { bool m_downloadFinished; // Is download complete? bool m_installFinished; // Is installation complete? bool m_downloadAbort; // Set to cause downloader to abort. bool m_installAbort; // Set to cause installer to abort. HRESULT m_hrDownloadFinished; // Resulting HRESULT for download. HRESULT m_hrInstallFinished; // Resulting HRESULT for installation. HRESULT m_hrInternalError; WCHAR m_szCurrentItemStep[MAX_PATH]; unsigned char m_downloadSoFar; // Download progress 0-255 (0-100% done). unsigned char m_installSoFar; // Installation progress 0-255 (0-100% done). WCHAR m_szEventName[MAX_PATH]; // Event that chainer creates and chainee opens to sync communications. BYTE m_version; // Version of the data structure, set by chainer: // 0x0: .NET Framework 4 // 0x1: .NET Framework 4.5 DWORD m_messageCode; // Current message sent by the chainee; 0 if no message is active. DWORD m_messageResponse; // Chainer's response to current message; 0 if not yet handled. DWORD m_messageDataLength; // Length of the m_messageData field, in bytes. BYTE m_messageData[1]; // Variable-length buffer; content depends on m_messageCode. };
Az
MmioDataStructure
adatstruktúrát nem szabad közvetlenül használni, hanem azMmioChainer
osztályt kell használnia a láncoló implementálásához. Az osztálybólMmioChainer
származtatva láncolhatja a .NET-keretrendszer 4.5 terjeszthető.
IProgressObserver.h
Az IProgressObserver.h fájl egy folyamatfigyelőt implementál. Ez a megfigyelő értesítést kap a letöltés és a telepítés előrehaladásáról (aláíratlanként
char
megadva, 0–255, ami 1–100%-os készültségi értéket jelez). A megfigyelő akkor is értesítést kap, ha a láncos üzenetet küld, és a megfigyelőnek választ kell küldenie.class IProgressObserver { public: virtual void OnProgress(unsigned char) = 0; // 0 - 255: 255 == 100% virtual void Finished(HRESULT) = 0; // Called when operation is complete virtual DWORD Send(DWORD dwMessage, LPVOID pData, DWORD dwDataLength) = 0; // Called when a message is sent };
ChainingdotNet4.5.cpp
A ChainingdotNet4.5.cpp fájl implementálja az
Server
osztályt, amely azMmioChainer
osztályból származik, és felülbírálja az előrehaladási adatok megjelenítéséhez szükséges megfelelő módszereket. Az MmioChainer létrehoz egy szakaszt a megadott szakasznévvel, és inicializálja a láncolót a megadott eseménynévvel. Az esemény nevét a rendszer a megfeleltetett adatstruktúrába menti. A szakaszokat és az eseményneveket egyedivé kell tenni. AzServer
alábbi kód osztálya elindítja a megadott telepítőprogramot, figyeli annak állapotát, és visszaad egy kilépési kódot.class Server : public ChainerSample::MmioChainer, public ChainerSample::IProgressObserver { public: ……………. Server():ChainerSample::MmioChainer(L"TheSectionName", L"TheEventName") //customize for your event names {}
A telepítés a Main metódusban indul el.
// Main entry point for program int __cdecl main(int argc, _In_count_(argc) char **_argv) { int result = 0; CString args; if (argc > 1) { args = CString(_argv[1]); } if (IsNetFx4Present(NETFX45_RC_REVISION)) { printf(".NET Framework 4.5 is already installed"); } else { result = Server().Launch(args); } return result; }
A telepítés elindítása előtt a láncoló ellenőrzi, hogy a .NET-keretrendszer 4.5 már telepítve van-e a következő hívással
IsNetFx4Present
:/// Checks for presence of the .NET Framework 4. /// A value of 0 for dwMinimumRelease indicates a check for the .NET Framework 4 full /// Any other value indicates a check for a specific compatible release of the .NET Framework 4. #define NETFX40_FULL_REVISION 0 // TODO: Replace with released revision number #define NETFX45_RC_REVISION MAKELONG(50309, 5) // .NET Framework 4.5 bool IsNetFx4Present(DWORD dwMinimumRelease) { DWORD dwError = ERROR_SUCCESS; HKEY hKey = NULL; DWORD dwData = 0; DWORD dwType = 0; DWORD dwSize = sizeof(dwData); dwError = ::RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"SOFTWARE\\Microsoft\\NET Framework Setup\\NDP\\v4\\Full", 0, KEY_READ, &hKey); if (ERROR_SUCCESS == dwError) { dwError = ::RegQueryValueExW(hKey, L"Release", 0, &dwType, (LPBYTE)&dwData, &dwSize); if ((ERROR_SUCCESS == dwError) && (REG_DWORD != dwType)) { dwError = ERROR_INVALID_DATA; } else if (ERROR_FILE_NOT_FOUND == dwError) { // Release value was not found, let's check for 4.0. dwError = ::RegQueryValueExW(hKey, L"Install", 0, &dwType, (LPBYTE)&dwData, &dwSize); // Install = (REG_DWORD)1; if ((ERROR_SUCCESS == dwError) && (REG_DWORD == dwType) && (dwData == 1)) { // treat 4.0 as Release = 0 dwData = 0; } else { dwError = ERROR_INVALID_DATA; } } } if (hKey != NULL) { ::RegCloseKey(hKey); } return ((ERROR_SUCCESS == dwError) && (dwData >= dwMinimumRelease)); }
A metódusban módosíthatja a végrehajtható (a példában
Launch
Setup.exe) elérési útját, hogy a megfelelő helyre mutasson, vagy testre szabhatja a kódot a hely meghatározásához. AzMmioChainer
alaposztály egy blokkolásiRun()
módszert biztosít, amelyet a származtatott osztály hív meg.bool Launch(const CString& args) { CString cmdline = L"dotNetFx45_Full_x86_x64.exe -pipe TheSectionName " + args; // Customize with name and location of setup .exe that you want to run STARTUPINFO si = {0}; si.cb = sizeof(si); PROCESS_INFORMATION pi = {0}; // Launch the Setup.exe that installs the .NET Framework 4.5 BOOL bLaunchedSetup = ::CreateProcess(NULL, cmdline.GetBuffer(), NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi); // If successful if (bLaunchedSetup != 0) { IProgressObserver& observer = dynamic_cast<IProgressObserver&>(*this); Run(pi.hProcess, observer); …………………….. return (bLaunchedSetup != 0); }
A
Send
metódus elfogja és feldolgozza az üzeneteket. A .NET-keretrendszer ezen verziójában az egyetlen támogatott üzenet a bezárt alkalmazásüzenet.// SendMessage // // Send a message and wait for the response. // dwMessage: Message to send // pData: The buffer to copy the data to // dwDataLength: Initially a pointer to the size of pBuffer. Upon successful call, the number of bytes copied to pBuffer. //-------------------------------------------------------------- virtual DWORD Send(DWORD dwMessage, LPVOID pData, DWORD dwDataLength) { DWORD dwResult = 0; printf("received message: %d\n", dwMessage); // Handle message switch (dwMessage) { case MMIO_CLOSE_APPS: { printf(" applications are holding files in use:\n"); IronMan::MmioCloseApplications* applications = reinterpret_cast<IronMan::MmioCloseApplications*>(pData); for(DWORD i = 0; i < applications->m_dwApplicationsSize; i++) { printf(" %ls (%d)\n", applications->m_applications[i].m_szName, applications->m_applications[i].m_dwPid); } printf(" should applications be closed? (Y)es, (N)o, (R)efresh : "); while (dwResult == 0) { switch (toupper(getwchar())) { case 'Y': dwResult = IDYES; // Close apps break; case 'N': dwResult = IDNO; break; case 'R': dwResult = IDRETRY; break; } } printf("\n"); break; } default: break; } printf(" response: %d\n ", dwResult); return dwResult; } };
A folyamatadatok 0 (0%) és 255 (100%) közötti aláírás
char
nélküli adatok.private: // IProgressObserver virtual void OnProgress(unsigned char ubProgressSoFar) {………… }
A HRESULT a metódusnak
Finished
lesz átadva.virtual void Finished(HRESULT hr) { // This HRESULT is communicated over MMIO and may be different than process // Exit code of the Chainee Setup.exe itself printf("\r\nFinished HRESULT: 0x%08X\r\n", hr); }
Fontos
A .NET-keretrendszer 4.5-ös újraterjeszthető általában sok előrehaladási üzenetet és egyetlen üzenetet ír, amely a befejezést jelzi (a láncos oldalon). Emellett aszinkron módon is beolvassa a
Abort
rekordokat. Ha egy rekordot kapAbort
, megszakítja a telepítést, és befejezett rekordot ír E_ABORT adatokként a telepítés megszakítása és a telepítési műveletek visszaállítása után.
Egy tipikus kiszolgáló létrehoz egy véletlenszerű MMIO-fájlnevet, létrehozza a fájlt (ahogyan az előző kódpéldában Server::CreateSection
is látható), és elindítja az terjeszthetőt a CreateProcess
metódus használatával, és átadja a pipa nevét a -pipe someFileSectionName
beállításnak. A kiszolgálónak alkalmazásspecifikus felhasználói felületi kóddal kell implementálnia OnProgress
a , Send
és Finished
metódusokat.
Lásd még
Visszajelzés
https://aka.ms/ContentUserFeedback.
Hamarosan elérhető: 2024-ben fokozatosan kivezetjük a GitHub-problémákat a tartalom visszajelzési mechanizmusaként, és lecseréljük egy új visszajelzési rendszerre. További információ:Visszajelzés küldése és megtekintése a következőhöz: