Megosztás a következőn keresztül:


Ú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:

    1. 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.

    2. 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 és m_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 és m_ installAbort jelzők beállításához m_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 az MmioChainer osztályt kell használnia a láncoló implementálásához. Az osztályból MmioChainer 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 charmegadva, 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 az MmioChainer 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. Az Server 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ássalIsNetFx4Present:

    ///  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. Az MmioChainer alaposztály egy blokkolási Run() 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 kap Abort , 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::CreateSectionis 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 OnProgressa , Sendés Finished metódusokat.

Lásd még