Delen via


Procedure: Voortgang ophalen van het .NET Framework 4.5-installatieprogramma

.NET Framework 4.5 is een herdistribueerbare runtime. Als u apps ontwikkelt voor deze versie van .NET Framework, kunt u .NET Framework 4.5 instellen als een vereist onderdeel van de installatie van uw app. Als u een aangepaste of uniforme installatie-ervaring wilt presenteren, wilt u het instellen van .NET Framework 4.5 op de achtergrond starten en de voortgang ervan bijhouden terwijl de voortgang van de installatie van uw app wordt weergegeven. Als u stille tracering wilt inschakelen, definieert .NET Framework 4.5 setup (die kan worden bekeken) een protocol met behulp van een door het geheugen toegewezen I/O-segment (MMIO) om te communiceren met uw installatie (de watcher of chainer). Dit protocol definieert een manier voor een chainer om voortgangsinformatie te verkrijgen, gedetailleerde resultaten te verkrijgen, berichten te beantwoorden en de installatie van .NET Framework 4.5 te annuleren.

  • Aanroepen. Als u .NET Framework 4.5-installatie wilt aanroepen en voortgangsgegevens wilt ontvangen uit de mmIO-sectie, moet uw installatieprogramma het volgende doen:

    1. Roep het herdistribueerbare programma van .NET Framework 4.5 aan:

      dotNetFx45_Full_x86_x64.exe /q /norestart /pipe section-name

      Waar de sectienaam een willekeurige naam is die u wilt gebruiken om uw app te identificeren. .NET Framework-installatie leest en schrijft asynchroon naar de MMIO-sectie, dus u kunt het handig vinden om gebeurtenissen en berichten gedurende die tijd te gebruiken. In het voorbeeld wordt het installatieproces van .NET Framework gemaakt door een constructor die de MMIO-sectie (TheSectionName) toewijst en een gebeurtenis definieert (TheEventName):

      Server():ChainerSample::MmioChainer(L"TheSectionName", L"TheEventName")
      

      Vervang deze namen door namen die uniek zijn voor uw installatieprogramma.

    2. Lees uit de MMIO-sectie. In .NET Framework 4.5 zijn de download- en installatiebewerkingen gelijktijdig: een deel van het .NET Framework kan worden geïnstalleerd terwijl een ander onderdeel wordt gedownload. Als gevolg hiervan wordt de voortgang teruggestuurd (dat wil gezegd, geschreven) naar de MMIO-sectie als twee getallen (m_downloadSoFar en m_installSoFar) die toenemen van 0 tot 255. Wanneer 255 is geschreven en .NET Framework wordt afgesloten, is de installatie voltooid.

  • Afsluitcodes. De volgende afsluitcodes van de opdracht om het herdistribueerbare programma van .NET Framework 4.5 aan te roepen, geven aan of de installatie is geslaagd of mislukt:

    • 0 - De installatie is voltooid.

    • 3010 – De installatie is voltooid; opnieuw opstarten van het systeem is vereist.

    • 1602 – Setup is geannuleerd.

    • Alle andere codes - Setup heeft fouten aangetroffen; bekijk de logboekbestanden die zijn gemaakt in %temp% voor meer informatie.

  • Setup wordt geannuleerd. U kunt de installatie op elk gewenst moment annuleren met behulp van de Abort methode om de m_downloadAbort en m_ installAbort vlaggen in te stellen in de MMIO-sectie.

Chainer-voorbeeld

Het Chainer-voorbeeld start op de achtergrond en houdt de installatie van .NET Framework 4.5 bij terwijl de voortgang wordt weergegeven. Dit voorbeeld is vergelijkbaar met het Chainer-voorbeeld dat is opgegeven voor .NET Framework 4. Daarnaast kan het systeem opnieuw opstarten voorkomen door het berichtvak te verwerken voor het sluiten van .NET Framework 4-apps. Zie Reduce System Restarts During .NET Framework 4.5 Installations (Systeem opnieuw opstarten verminderen) voor meer informatie over dit berichtvak. U kunt dit voorbeeld gebruiken met het .NET Framework 4-installatieprogramma; In dat scenario wordt het bericht gewoon niet verzonden.

Waarschuwing

U moet het voorbeeld uitvoeren als beheerder.

In de volgende secties worden de belangrijke bestanden in dit voorbeeld beschreven: MMIOChainer.h, ChainingdotNet4.cpp en IProgressObserver.h.

MMIOChainer.h

  • Het MMIOChainer.h-bestand bevat de definitie van de gegevensstructuur en de basisklasse waaruit de chainerklasse moet worden afgeleid. Met .NET Framework 4.5 wordt de MMIO-gegevensstructuur uitgebreid om gegevens te verwerken die het .NET Framework 4.5-installatieprogramma nodig heeft. De wijzigingen in de MMIO-structuur zijn achterwaarts compatibel, zodat een .NET Framework 4-chainer kan werken met .NET Framework 4.5-installatie zonder dat er opnieuw hoeft te worden gecompileerde. Dit scenario biedt echter geen ondersteuning voor de functie voor het verminderen van het opnieuw opstarten van het systeem.

    Een versieveld biedt een middel om revisies in de structuur en berichtindeling te identificeren. De installatie van .NET Framework bepaalt de versie van de chainer-interface door de VirtualQuery functie aan te roepen om de grootte van de bestandstoewijzing te bepalen. Als de grootte groot genoeg is voor het versieveld, gebruikt .NET Framework setup de opgegeven waarde. Als de bestandstoewijzing te klein is om een versieveld te bevatten, wat het geval is bij .NET Framework 4, wordt bij het installatieproces uitgegaan van versie 0 (4). Als de chainer geen ondersteuning biedt voor de versie van het bericht dat .NET Framework-installatie wil verzenden, wordt in .NET Framework een genegeerd antwoord aangenomen.

    De MMIO-gegevensstructuur wordt als volgt gedefinieerd:

    // 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.
        };
    
  • De MmioDataStructure gegevensstructuur mag niet rechtstreeks worden gebruikt. Gebruik in plaats daarvan de MmioChainer klasse om uw chainer te implementeren. Afgeleid van de MmioChainer klasse om het herdistribueerbare .NET Framework 4.5 te koppelen.

IProgressObserver.h

  • Het bestand IProgressObserver.h implementeert een voortgangsobator. Deze waarnemer ontvangt een melding over de voortgang van de download en installatie (opgegeven als een niet-ondertekende char, 0-255, wat 1%-100% voltooid aangeeft). De waarnemer wordt ook op de hoogte gesteld wanneer de chainee een bericht verzendt en de waarnemer een antwoord moet verzenden.

        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

  • Het bestand ChainingdotNet4.5.cpp implementeert de Server klasse, die is afgeleid van de MmioChainer klasse en overschrijft de juiste methoden om voortgangsinformatie weer te geven. MmioChainer maakt een sectie met de opgegeven sectienaam en initialiseert de chainer met de opgegeven gebeurtenisnaam. De gebeurtenisnaam wordt opgeslagen in de toegewezen gegevensstructuur. U moet de sectie- en gebeurtenisnamen uniek maken. De Server klasse in de volgende code start het opgegeven installatieprogramma, bewaakt de voortgang en retourneert een afsluitcode.

    class Server : public ChainerSample::MmioChainer, public ChainerSample::IProgressObserver
    {
    public:
        …………….
        Server():ChainerSample::MmioChainer(L"TheSectionName", L"TheEventName") //customize for your event names
        {}
    

    De installatie wordt gestart in de Main-methode.

    // 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;
    }
    
  • Voordat de installatie wordt gestart, controleert de chainer of .NET Framework 4.5 al is geïnstalleerd door het aanroepen IsNetFx4Presentvan:

    ///  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));
    }
    
  • U kunt het pad van het uitvoerbare bestand (Setup.exe in het voorbeeld) in de methode wijzigen om naar de Launch juiste locatie te verwijzen of de code aanpassen om de locatie te bepalen. De MmioChainer basisklasse biedt een blokkeringsmethode Run() die door de afgeleide klasse wordt aangeroepen.

    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);
    }
    
  • De Send methode onderschept en verwerkt de berichten. In deze versie van .NET Framework is het enige ondersteunde bericht het toepassingsbericht sluiten.

            // 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;
        }
    };
    
  • Voortgangsgegevens zijn niet ondertekend char tussen 0 (0%) en 255 (100%).

    private: // IProgressObserver
        virtual void OnProgress(unsigned char ubProgressSoFar)
        {…………
       }
    
  • Het HRESULT wordt doorgegeven aan de Finished methode.

    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);
    }
    

    Belangrijk

    Het herdistribueerbare .NET Framework 4.5 schrijft doorgaans veel voortgangsberichten en één bericht dat aangeeft dat de voltooiing is voltooid (aan de kant van de chainer). Het leest ook asynchroon, op zoek naar Abort records. Als er een Abort record wordt ontvangen, wordt de installatie geannuleerd en wordt een voltooide record met E_ABORT geschreven als de gegevens nadat de installatie is afgebroken en de installatiebewerkingen zijn teruggedraaid.

Een typische server maakt een willekeurige MMIO-bestandsnaam, maakt het bestand (zoals wordt weergegeven in het vorige codevoorbeeld, in Server::CreateSection) en start het herdistribueerbare bestand met behulp van de CreateProcess methode en geeft de pijpnaam door met de -pipe someFileSectionName optie. De server moet , en Finished methoden implementeren OnProgressSendmet toepassingsspecifieke code voor de gebruikersinterface.

Zie ook