方法: .NET Framework 4.5 インストーラーの進行状況を表示するHow to: Get Progress from the .NET Framework 4.5 Installer

.NET Framework 4.5 は再頒布可能なランタイムです。The .NET Framework 4.5 is a redistributable runtime. このバージョンの .NET Framework 用アプリを開発する場合は、アプリのセットアップに必要なパーツとして、.NET Framework 4.5 セットアップを含める (チェーンする) ことができます。If you develop apps for this version of the .NET Framework, you can include (chain) .NET Framework 4.5 setup as a prerequisite part of your app's setup. セットアップ手順をカスタマイズまたは統一するために、アプリのセットアップの進行状況を表示しながら、.NET Framework 4.5 セットアップをサイレントで起動し、その進行状況を追跡できます。To present a customized or unified setup experience, you may want to silently launch .NET Framework 4.5 setup and track its progress while showing your app's setup progress. サイレントな追跡を可能にするために、.NET Framework 4.5 セットアップ (監視対象) ではメモリ マップ I/O (MMIO) セグメントを使用することでプロトコルを定義し、セットアップ (ウォッチャーまたはチェーン元) と通信します。To enable silent tracking, .NET Framework 4.5 setup (which can be watched) defines a protocol by using a memory-mapped I/O (MMIO) segment to communicate with your setup (the watcher or chainer). このプロトコルは、チェーン元による進行状況情報の取得、詳細な結果の取得、メッセージへの応答、.NET Framework 4.5 セットアップの取り消しを行う方法を定義します。This protocol defines a way for a chainer to obtain progress information, get detailed results, respond to messages, and cancel the .NET Framework 4.5 setup.

  • 呼び出しInvocation. .NET Framework 4.5 セットアップを呼び出して、MMIO セクションから進行状況情報を受け取るには、セットアップ プログラムで以下の処理を行う必要があります。To call .NET Framework 4.5 setup and receive progress information from the MMIO section, your setup program must do the following:

    1. .NET Framework 4.5 再頒布可能プログラムを呼び出します。Call the .NET Framework 4.5redistributable program:

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

      この section name は、アプリの識別に使用する名前です。Where section name is any name you want to use to identify your app. .NET Framework のセットアップでは MMIO セクションに対する読み書きを非同期に行うので、その間、イベントおよびメッセージの使用が役立つ場合があります。.NET Framework setup reads and writes to the MMIO section asynchronously, so you might find it convenient to use events and messages during that time. この例では、.NETFramework セットアップ プロセスは、MMIO セクションの割り当て (TheSectionName) とイベントの定義 (TheEventName) の両方を行うコンストラクターによって作成されます。In the example, the .NET Framework setup process is created by a constructor that both allocates the MMIO section (TheSectionName) and defines an event (TheEventName):

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

      これらの名前は、実際のセットアップ プログラムの固有な名前に置き換えてください。Please replace those names with names that are unique to your setup program.

    2. MMIO セクションから読み取ります。Read from the MMIO section. .NET Framework 4.5 では、ダウンロード操作とインストール操作は同時に行われます。 .NET Framework の 1 つのパーツがインストールしている間に、別のパーツがダウンロードします。In the .NET Framework 4.5, the download and installation operations are simultaneous: One part of the .NET Framework might be installing while another part is downloading. その結果、進行状況は、0 から 255 まで増加する 2 つの値 (m_downloadSoFar および m_installSoFar) として MMIO セクションに送り返されます (書き込まれます)。As a result, progress is sent back (that is, written) to the MMIO section as two numbers (m_downloadSoFar and m_installSoFar) that increase from 0 to 255. 255 が書き込まれて、.NET Framework が終了すると、インストールは完了します。When 255 is written and the .NET Framework exits, the installation is complete.

  • 終了コードExit codes. .NET Framework 4.5 再頒布可能プログラムを呼び出すためのコマンドからの以下の終了コードは、セットアップが成功または失敗したことを示します。The following exit codes from the command to call the .NET Framework 4.5 redistributable program indicate whether setup has succeeded or failed:

    • 0: セットアップは、正常に完了しました。0 - Setup completed successfully.

    • 3010: セットアップは正常に完了しました。システムの再起動が必要です。3010 – Setup completed successfully; a system restart is required.

    • 1602: セットアップは取り消されました。1602 – Setup has been canceled.

    • 他のすべてのコード: セットアップでエラーが発生しました。詳細については、%temp% に作成されるログ ファイルを調べてください。All other codes - Setup encountered errors; examine the log files created in %temp% for details.

  • セットアップの取り消しCanceling setup. Abort メソッドを使用して MMIO セクションの m_downloadAbort フラグと m_ installAbort フラグを設定することで、いつでもセットアップを取り消すことができます。You can cancel setup at any time by using the Abort method to set the m_downloadAbort and m_ installAbort flags in the MMIO section.

チェーン元のサンプルChainer Sample

チェーン元のサンプルが、進行状況を表示しながらサイレントで起動し、.NET Framework 4.5 セットアップを追跡します。The Chainer sample silently launches and tracks .NET Framework 4.5 setup while showing progress. このサンプルは、.NET Framework 4 用のチェーン元サンプルに似ています。This sample is similar to the Chainer sample provided for the .NET Framework 4. ただし、.NET Framework 4 アプリケーションを閉じるためのメッセージ ボックスを処理することで、システムの再起動を避けることができます。However, in addition, it can avoid system restarts by processing the message box for closing .NET Framework 4 apps. このメッセージ ボックスの詳細については、「.NET Framework 4.5 のインストール中のシステム再起動の削減」を参照してください。For information about this message box, see Reducing System Restarts During .NET Framework 4.5 Installations. このサンプルは .NET Framework 4 インストーラーで使用できます。そのシナリオではメッセージは送信されません。You can use this sample with the .NET Framework 4 installer; in that scenario, the message is simply not sent.

警告

例の実行は、管理者として行う必要があります。You must run the example as an administrator.

MSDN サンプル ギャラリーから .NET Framework 4.5 チェーン元のサンプルの完全な Visual Studio ソリューションをダウンロードできます。You can download the complete Visual Studio solution for the .NET Framework 4.5 Chainer Sample from the MSDN Samples Gallery.

以下のセクションでは、この例の重要なファイルである MMIOChainer.h、ChainingdotNet4.cpp、および IProgressObserver.h について説明します。The following sections describe the significant files in this sample: MMIOChainer.h, ChainingdotNet4.cpp, and IProgressObserver.h.

MMIOChainer.hMMIOChainer.h

  • MMIOChainer.h ファイル (完全なコードを参照) には、データ構造体の定義と、チェーン元クラスが派生する基底クラスが含まれます。The MMIOChainer.h file (see complete code) contains the data structure definition and the base class from which the chainer class should be derived. .NET Framework 4.5 によって、MMIO データ構造体が拡張され、.NET Framework 4.5 インストーラーが必要とするデータが処理されます。The .NET Framework 4.5 extends the MMIO data structure to handle data that the .NET Framework 4.5 installer needs. MMIO 構造体への変更には下位互換性があるため、.NET Framework 4 チェーン元は、再コンパイルを必要とせずに .NET Framework 4.5 のセットアップで機能します。The changes to the MMIO structure are backward-compatible, so a .NET Framework 4 chainer can work with .NET Framework 4.5 setup without requiring recompilation. ただし、このシナリオはシステムの再起動を削減するための機能をサポートしていません。However, this scenario does not support the feature for reducing system restarts.

    バージョン フィールドは、構造体およびメッセージ形式へのリビジョンを識別するための手段を提供します。A version field provides a means of identifying revisions to the structure and message format. .NET Framework セットアップでは、VirtualQuery 関数を呼び出してファイル マップのサイズを判断することで、チェーン元インターフェイスのバージョンを判別します。The .NET Framework setup determines the version of the chainer interface by calling the VirtualQuery function to determine the size of the file mapping. サイズがバージョン フィールドに対応できる十分な大きさである場合、.NET Framework セットアップでは指定された値を使用します。If the size is large enough to accommodate the version field, .NET Framework setup uses the specified value. .NET Framework 4 の場合のように、バージョン フィールドを含めるにはファイル マップが小さすぎる場合、セットアップ プロセスではバージョン 0 (4) を使用します。If the file mapping is too small to contain a version field, which is the case with the .NET Framework 4, the setup process assumes version 0 (4). .NET Framework セットアップが送信しようとするメッセージのバージョンをチェーン元がサポートしていない場合、.NET Framework セットアップでは応答を無視します。If the chainer does not support the version of the message that .NET Framework setup wants to send, .NET Framework setup assumes an ignore response.

    MMIO データ構造体は以下のように定義されます。The MMIO data structure is defined as follows:

    // 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.
        };
    
  • MmioDataStructure データ構造体を直接使用するのではなく、チェーン元を実装するための MmioChainer クラスを使用します。The MmioDataStructure data structure should not be used directly; use the MmioChainer class instead to implement your chainer. MmioChainer クラスから派生させて、.NET Framework 4.5 再頒布可能プログラムをチェーンします。Derive from the MmioChainer class to chain the .NET Framework 4.5 redistributable.

IProgressObserver.hIProgressObserver.h

  • IProgressObserver.h ファイルは進行状況のオブザーバー (完全なコードを参照) を実装します。The IProgressObserver.h file implements a progress observer (see complete code). このオブザーバーは、ダウンロードとインストールの進行状況 (1% ~ 100% 完了を示す、符号なしの char 0 ~ 255 の値で指定) の通知を受け取ります。This observer gets notified of download and installation progress (specified as an unsigned char, 0-255, indicating 1%-100% complete). オブザーバーは、チェーン対象がメッセージを送信したときにも通知を受け取ります。通知を受け取ったオブザーバーは、応答を送信する必要があります。The observer is also notified when the chainee sends a message, and the observer should send a response.

        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.cppChainingdotNet4.5.cpp

  • ChainingdotNet4.5.cpp ファイルは、Server クラスを実装します。このクラスは MmioChainer クラスから派生し、適切なメソッドをオーバーライドして進行状況情報を表示します。The ChainingdotNet4.5.cpp file implements the Server class, which derives from the MmioChainer class and overrides the appropriate methods to display progress information. MmioChainer は、指定されたセクション名でセクションを作成し、指定されたイベント名でチェーン元を初期化します。The MmioChainer creates a section with the specified section name and initializes the chainer with the specified event name. イベント名は、マップされたデータ構造体に保存されます。The event name is saved in the mapped data structure. セクションとイベント名は一意にする必要があります。You should make the section and event names unique. 次のコードの Server クラスは、指定されたセットアップ プログラムを起動して進行状況を監視し、終了コードを返します。The Server class in the following code launches the specified setup program, monitors its progress, and returns an exit code.

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

    インストールが Main メソッドで開始されます。The installation is started in the Main method.

    // 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;
    }
    
  • インストールを始める前に、チェーン元では IsNetFx4Present を呼び出して、.NET Framework 4.5 が既にインストールされているかどうかの確認が行われます。Before launching the installation, the chainer checks to see if the .NET Framework 4.5 is already installed by calling 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));
    }
    
  • Launch メソッド内の実行可能ファイル (例では Setup.exe) のパスを正しい場所に変更するか、コードをカスタマイズして場所を判断することができます。You can change the path of the executable (Setup.exe in the example) in the Launch method to point to its correct location, or customize the code to determine the location. MmioChainer 基底クラスは、派生クラスが呼び出すブロッキング Run() メソッドを提供します。The MmioChainer base class provides a blocking Run() method that the derived class calls.

    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);
    }
    
  • Send メソッドはメッセージを途中受信して処理します。The Send method intercepts and processes the messages. このバージョンの .NET Framework では、サポートされているメッセージはアプリケーションの終了メッセージのみです。In this version of the .NET Framework, the only supported message is the close application message.

            // 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 appliations 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;
        }
    };
    
  • 進行状況のデータは、0 (0%) ~ 255 (100%) の範囲の符号なし char です。Progress data is an unsigned char between 0 (0%) and 255 (100%).

    private: // IProgressObserver
        virtual void OnProgress(unsigned char ubProgressSoFar)
        {…………
       }
    
  • HRESULT は、Finished メソッドに渡されます。The HRESULT is passed to the Finished method.

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

    重要

    .NET Framework 4.5 の再頒布可能プログラムによって、通常、多数の進行状況メッセージと、(チェーン元側で) 完了を示す 1 つのメッセージが書き込まれます。The .NET Framework 4.5 redistributable typically writes many progress messages and a single message that indicates completion (on the chainer side). また、非同期に読み取りを行って、Abort レコードを探します。It also reads asynchronously, looking for Abort records. Abort レコードを受け取った場合は、インストールを取り消し、インストールが中止され、セットアップ操作がロールバックされた後に、データとして E_ABORT を含む終了レコードを書き込みます。If it receives an Abort record, it cancels the installation, and writes a finished record with E_ABORT as its data after the installation has been aborted and setup operations have been rolled back.

標準的なサーバーは、ランダムな MMIO ファイル名を作成し、ファイル (前のコード例の Server::CreateSection で示されているファイル) を作成した後、CreateProcess メソッドを使用して -pipe someFileSectionName オプションでパイプ名を渡すことによって、再頒布可能プログラムを起動します。A typical server creates a random MMIO file name, creates the file (as shown in the previous code example, in Server::CreateSection), and launches the redistributable by using the CreateProcess method and passing the pipe name with the -pipe someFileSectionName option. サーバーは、アプリケーションの UI 固有のコードを使用して OnProgressSend、および Finished の各メソッドを実装する必要があります。The server should implement OnProgress, Send, and Finished methods with application UI-specific code.

関連項目See also