Io mi sono scritto un script per Inno Setup, molto semplice da usare... e soprattuto freeware in tutti i sensi... questo modulo verifica la presenza del framework 2.0 e se non c'è lo scarica e lo installa anche...

codice:
// *************************************
// VERIFICA LA PRESENZA DI FRAMEWORK 2.0
// *************************************
//
// Inizializzo le variabili dello script
var
dotnetSource: string;
dotnetDownNecessario: boolean;
dotnetNecessario: boolean;
dotnetRiepilogo: string;
//
// Le dichiarazione external servono per richiamare una procedura o funzione
// da una DLL (Dinamic Link Library) esistente nel sistema operativo,
// di cui si deve conoscere il nome.
// Il nome delle procedure/funzione può essere scelto a proprio piacere, mentre
// i parametri devono essere perfettamente identici a quelli della procedura/funzione da richiamare.
//
// Esempio procedure:
// procedure <nome>(<parametri>)
// external <nome libreria> name <nome procedura da richiamare>
//
// Esempio funzioni:
// function <nome>(<parametri>):<tipo>
// external <nome libreria> name <nome funzione da richiamare>
//
procedure isxdl_AddFile(URL, Filename: PChar);
external 'isxdl_AddFile@files:isxdl.dll stdcall';
//
function isxdl_DownloadFiles(hWnd: Integer): Integer;
external 'isxdl_DownloadFiles@files:isxdl.dll stdcall';
//
function isxdl_SetOption(Option, Value: PChar): Integer;
external 'isxdl_SetOption@files:isxdl.dll stdcall';
//
//
// Definisco le costanti
const
dotnetRedistURL = 'http://www.microsoft.com/downloads/info.aspx?na=90&p=&SrcDisplayLang=it&SrcCategoryId=&SrcFamilyId=0856eacb-4362-4b0d-8edd-aab15c5e04f5&u=http%3a%2f%2fdownload.microsoft.com%2fdownload%2f5%2f6%2f7%2f567758a3-759e-473e-bf8f-52154438565a%2fdotnetfx.exe';
// Per i test in locale:   
// dotnetRedistURL = 'http://192.168.1.1/dotnetfx.exe';
//
// Funzione di base chiamata quando l'installazione parte
function InitializeSetup(): Boolean;
  // Creo la variabile che conterrò il risultato della funzione e la imposto su true
  begin
  // Risultato funzione : assume un valore per mezzo dell’operatore :=
  Result := true;
  dotnetNecessario := false;
  //
  // Per verificare se esiste il framework:
  // in tutti i casi per maggiori dettagli potete consultare:
  // http://support.microsoft.com/?scid=k...15291&x=7&y=17
  //
  // Per il .NET Framework, 1,0:
  // HKEY LOCAL MACHINE\SOFTWARE\Microsoft\.NETFramework\policy\v1.0
  //
  // Per il .NET Framework 1.1:
  // HKEY LOCAL MACHINE\SOFTWARE\Microsoft\.NETFramework\policy\v1.1
  //
  // Per il .NET Framework, 2,0:
  // HKEY LOCAL MACHINE\SOFTWARE\Microsoft\.NETFramework\policy\v2.0
  //
  // Controllo se è installato il framework
  if (not RegKeyExists(HKLM, 'SOFTWARE\Microsoft\.NETFramework\policy\v2.0')) then begin
    // Se la chiave di registro non esiste imposto il download "necessario" quindi true
    dotnetNecessario := true;
    // Se non si posseggono i requisiti di Admin l'istallazione termina
    if (not IsAdminLoggedOn()) then begin
      MsgBox('Per poter installare Framework .NET 2.0 è necessario essere loggato come Amministratore del sistema (Admin)', mbInformation, MB_OK);
      // Risultato funzione : assume un valore per mezzo dell’operatore :=
      Result := false;
      // Altrimenti se si posseggono i requisti
    end else begin
      dotnetRiepilogo := dotnetRiepilogo + '      .NET Framework v.2.0' #13;
      // Verifico se il file è presente nella cartella dove è presente il setup
      dotnetSource := ExpandConstant('{src}\dotnetfx.exe');
      // Se il file non esiste
      if not FileExists(dotnetSource) then begin
        // Imposto la cartella di destinazione per il download
        dotnetSource := ExpandConstant('{tmp}\dotnetfx.exe');
        // Verifico sempre se il file esiste
        if not FileExists(dotnetSource) then begin
          // Richiamo la procedura della della libreria isxdl.dll
          // dove il primo argomento è l'url e il secondo la destinazione
          isxdl_AddFile(dotnetRedistURL, dotnetSource);
          // Imposto la variabile su true
          dotnetDownNecessario := true;
        end;
      end;
      // Scrivo una stringa in un file ini
      // function SetIniString(const Section, Key, Value, Filename: String): Boolean;
      //
      // Cambi tutte le costanti in S ai loro valori. Per esempio, ExpandConstant ('{srcexe}') è sostituito dal nome del setup.
      // function ExpandConstant(const S: String): String;
      SetIniString('install', 'dotnetRedist', dotnetSource, ExpandConstant('{tmp}\dep.ini'));
    end;
  end;
end;
//
// Funzione richiamata ogni qualvolta si clicca sul pulsante Avanti
function NextButtonClick(CurPageID: Integer): Boolean;
// Inizializzo le variabili
// esse servono solo ed esclusivamente all’interno della funzione (o procedura)
// per semplificare il calcolo e non sono accessibili al di fuori di essa, in
// quanto la memoria loro assegnata viene liberata al termine della funzione.
var
  hWnd: Integer;
  ResultCode: Integer;
begin
  // Risultato funzione : assume un valore per mezzo dell’operatore :=
  Result := true;
  // CurPageID valori di default:
  // wpWelcome, wpLicense, wpPassword, wpInfoBefore, wpUserInfo, wpSelectDir,
  // wpSelectComponents, wpSelectProgramGroup, wpSelectTasks, wpReady, wpPreparing,
  // wpInstalling, wpInfoAfter, wpFinished
  //
  // Se l'id della pagina corrente è uguale alla pagina Ready
  if CurPageID = wpReady then begin
    //
    // wizardhwnd :     Prende il valore dell'handle della finestra di installazione.
    //                  This handle is set to '0' if the wizard window handle isn't available at the time the translation is done.
    //
    // ExpandConstant : Changes all constants in S to their values.
    //                  For example, ExpandConstant('{srcexe}') is changed to the filename of Setup.
    //
    // StrToInt :       The StrToInt function converts the string passed in S into a number
    //
    hWnd := StrToInt(ExpandConstant('{wizardhwnd}'));
    // don't try to init isxdl if it's not needed because it will error on < ie 3
    if dotnetDownNecessario = true then
    //
    begin
      // Definisco alcune opzioni per il wizard del file
      // Currently these options can be set:
      // Option = Value
      // Title : The title to use for the download window.
      // Debug : Not used. Valid values are "true" and "false".
      // Simple : Turns on simple mode if the value is a string, turns off simple mode if the value is an empty string.
      // Label : Text for header label.
      // Description : Text for header description.
      // Language : Language file to get texts from.
      // Resume : Tell it to use resume. Default is true. (Disabled.)
      // Smallwizardimage : The image to display if you want something other than the default
      isxdl_SetOption('label', 'Installazione di Microsoft .NET Framework');
      isxdl_SetOption('description', 'Il software ha bisogno di Microsoft .NET Framework. Attendere per favore.');
      isxdl_SetOption('language', 'C:\Programmi\Download DLL\languages\italian.ini');
      // isxdl_DownloadFiles : Downloads all files added with isxdl_AddFile or isxdl_AddFileSize
      if isxdl_DownloadFiles(hWnd) = 0 then Result := false;
    end;
    //
    if (Result = true) and (dotnetNecessario = true) then begin
      // Exec : Esegui un file exe o un file batch. Returns True if the specified file was executed successfully, False otherwise
      // function Exec(const Filename, Params, WorkingDir: String; const ShowCmd: Integer; const Wait: TExecWait; var ResultCode: Integer): Boolean;
      // ewWaitUntilTerminated : attendi fino a che non ha terminato
      if Exec(ExpandConstant(dotnetSource), '', '', SW_SHOW, ewWaitUntilTerminated, ResultCode) = true then begin
         // handle success if necessary; ResultCode contains the exit code
         if not (ResultCode = 0) then begin
           Result := false;
         end;
      end else begin
         // handle failure if necessary; ResultCode contains the error code
         Result := false;
      end;
    end;
  end;
end;
//
function UpdateReadyMemo(Space, NewLine, MemoUserInfoInfo, MemoDirInfo, MemoTypeInfo, MemoComponentsInfo, MemoGroupInfo, MemoTasksInfo: String): String;
// If Setup finds the UpdateReadyMemo event function in the Pascal script,
// it is called automatically when the Ready to Install wizard page becomes the active page.
// It should return the text to be displayed in the settings memo on the Ready to Install wizard page
// as a single string with lines separated by the NewLine parameter.
// Parameter Space contains a string with spaces. Setup uses this string to indent settings.
// Gli altri parametri contengono le stringhe (eventualemente vuote) che il Setup ha utilizzato come setting.
// Il parametro MemoDirInfo per esempio contiente la stringa della cartella di destinazione del programma.
// Restituisce False se si annulla l'operazione
//
// Inizializzo la variabile
var
 s: string;
 begin
   if dotnetRiepilogo <> '' then
     s := s + 'Installazione necessaria:' + NewLine + dotnetRiepilogo + NewLine;
     s := s + MemoDirInfo + NewLine + NewLine;
     Result := s
 end;