¿Cómo puedo instalar .NET Framework como requisito previo usando InnoSetup?

Tengo una pregunta similar a Inno Setup: compruebe que .NET 4.0 está instalado , pero parece ser ligeramente diferente.

[Files] Source: "dependencies\dotNetFx40_Full_x86_x64.exe"; DestDir: {tmp}; Flags: deleteafterinstall; Check: FrameworkIsNotInstalled Source: "C:\Windows\Microsoft.NET\assembly\GAC_MSIL\MySql.Data\v4.0_6.5.4.0__c5687fc88969c44d\MySql.Data.dll"; DestDir: "{app}\lib"; StrongAssemblyName: "MySql.Data, Version=6.5.4.0, Culture=neutral, PublicKeyToken=c5687fc88969c44d, ProcessorArchitecture=MSIL"; Flags: "gacinstall sharedfile uninsnosharedfileprompt" [Run] Filename: {tmp}\dotNetFx40_Full_x86_x64.exe; Description: Install Microsoft .NET Framework 4.0; Parameters: /q /norestart; Check: FrameworkIsNotInstalled [code] function FrameworkIsNotInstalled: Boolean; begin Result := not RegKeyExists(HKEY_LOCAL_MACHINE, 'Software\Microsoft\.NETFramework\policy\v4.0'); end; 

Como puede ver, estoy intentando registrar un archivo con el GAC. Desafortunadamente, en algunas máquinas es posible que .NET Framework no esté instalado. Entonces necesito instalarlo primero. ¿Hay alguna forma de que pueda forzar una instalación del tiempo de ejecución de .NET antes de intentar registrar mis archivos?

Dado que la sección [Run] se procesa después de la sección [Files] , es naturalmente imposible hacerlo con el script que ha mostrado (de ahí su pregunta). Hay algunas formas en que la que recomendaría es ejecutar la configuración de .NET desde la función de parámetro AfterInstall de la entrada de configuración propiamente dicha. Entonces eliminaría su sección actual [Run] y escribiría un script como este:

 [Files] Source: "dependencies\dotNetFx40_Full_x86_x64.exe"; DestDir: {tmp}; Flags: deleteafterinstall; AfterInstall: InstallFramework; Check: FrameworkIsNotInstalled Source: "C:\Windows\Microsoft.NET\assembly\GAC_MSIL\MySql.Data\v4.0_6.5.4.0__c5687fc88969c44d\MySql.Data.dll"; DestDir: "{app}\lib"; StrongAssemblyName: "MySql.Data, Version=6.5.4.0, Culture=neutral, PublicKeyToken=c5687fc88969c44d, ProcessorArchitecture=MSIL"; Flags: gacinstall sharedfile uninsnosharedfileprompt [Code] procedure InstallFramework; var ResultCode: Integer; begin if not Exec(ExpandConstant('{tmp}\dotNetFx40_Full_x86_x64.exe'), '/q /norestart', '', SW_SHOW, ewWaitUntilTerminated, ResultCode) then begin { you can interact with the user that the installation failed } MsgBox('.NET installation failed with code: ' + IntToStr(ResultCode) + '.', mbError, MB_OK); end; end; 

El proceso es sencillo, si la función Check de la entrada de configuración .NET de la sección [Files] se evalúa como Verdadero ( FrameworkIsNotInstalled ), la entrada se procesa, lo que copia el archivo binario de instalación en la carpeta temporal de la Configuración Inno y si eso tiene éxito, el Función AfterInstall InstallFramework se llama inmediatamente después. Dentro de esta función, la configuración .NET se ejecuta manualmente llamando a la función Exec .

Y finalmente, si todo eso tiene éxito, la instalación continúa procesando la siguiente entrada de la sección [Files] , que es el ensamblado que se va a registrar. Ahora, con el framework .NET instalado. Como puede ver, el orden de las entradas de la sección [Files] es crucial aquí.


Además, en su comentario ha preguntado cómo mostrarle al usuario algún progreso, ya que al ejecutar la configuración de .NET de la manera en que lo he publicado aquí, bloquea la entrada de [Files] , que muestra la barra de progreso detenida y el texto sobre extrayendo archivos. Como no sería fácil obtener el progreso de instalación de la instalación de .NET, simplemente mostraría al usuario una barra de progreso de marquesina sin fin durante la ejecución de la configuración.

Para hacer esto, ajuste la ejecución de la configuración en un código como este:

 procedure InstallFramework; var StatusText: string; begin StatusText := WizardForm.StatusLabel.Caption; WizardForm.StatusLabel.Caption := 'Installing .NET framework...'; WizardForm.ProgressGauge.Style := npbstMarquee; try { here put the .NET setup execution code } finally WizardForm.StatusLabel.Caption := StatusText; WizardForm.ProgressGauge.Style := npbstNormal; end; end; 

Así es como se ve el formulario del asistente durante la ejecución de la configuración de .NET (la barra de progreso está animada):

enter image description here

Solo quiero agregar algo a @TLama: el cierre cuando falla la instalación. No es tan fácil porque WizardForm.Close; solo invoca el botón cancelar que el usuario puede cancelar. Finalmente, el código puede verse así:

 [Code] var CancelWithoutPrompt: boolean; function InitializeSetup(): Boolean; begin CancelWithoutPrompt := false; result := true; end; procedure CancelButtonClick(CurPageID: Integer; var Cancel, Confirm: Boolean); begin if CurPageID=wpInstalling then Confirm := not CancelWithoutPrompt; end; function FrameworkIsNotInstalled: Boolean; begin Result := not RegKeyExists(HKEY_LOCAL_MACHINE, 'SOFTWARE\Microsoft\NET Framework Setup\NDP\v4\Full'); end; procedure InstallFramework; var StatusText: string; ResultCode: Integer; begin StatusText := WizardForm.StatusLabel.Caption; WizardForm.StatusLabel.Caption := 'Installing .NET framework...'; WizardForm.ProgressGauge.Style := npbstMarquee; try if not Exec(ExpandConstant('{tmp}\dotNetFx45_Full_asetup.exe'), '/q /norestart', '', SW_SHOW, ewWaitUntilTerminated, ResultCode) then begin // you can interact with the user that the installation failed MsgBox('.NET installation failed with code: ' + IntToStr(ResultCode) + '.', mbError, MB_OK); CancelWithoutPrompt := true; WizardForm.Close; end; finally WizardForm.StatusLabel.Caption := StatusText; WizardForm.ProgressGauge.Style := npbstNormal; end; end; 

solo mis 2 centavos al buscar .NET Framework 4.7, encaja perfectamente con la respuesta de @ Snicker:

 function FrameworkIsNotInstalled: Boolean; var ver: Cardinal; begin Result := not ( (RegKeyExists( HKEY_LOCAL_MACHINE, 'SOFTWARE\Microsoft\NET Framework Setup\NDP\v4\Client') and RegQueryDWordValue(HKEY_LOCAL_MACHINE, 'SOFTWARE\Microsoft\NET Framework Setup\NDP\v4\Client', 'Release', ver) ) or (RegKeyExists( HKEY_LOCAL_MACHINE, 'SOFTWARE\Microsoft\NET Framework Setup\NDP\v4\Full') and RegQueryDWordValue(HKEY_LOCAL_MACHINE, 'SOFTWARE\Microsoft\NET Framework Setup\NDP\v4\Full', 'Release', ver) ) ) and (ver < 460798) end;