5

I am using Inno Setup located here http://www.jrsoftware.org/

I am also using Modular InnoSetup Dependency Installer located here http://www.codeproject.com/Articles/20868/NET-Framework-Installer-for-InnoSetup

I have a project that needs the Visual C++ Redistributable Package for Visual Studio 2013 located here. http://www.microsoft.com/en-us/download/details.aspx?id=40784

I am trying to modify a product file from the Modular Inno Seup Dependency installer. I have copied and modified the file from vcredist2010.iss to vcredist2013.iss but the problem is that every time it installs it re-downloads the C++ 2013 run time. I don't think it's detecting the install so it's reinstalling every time.

Here is the code I currently have..

// requires Windows 7 Service Pack 1, Windows 8, Windows 8.1, Windows Server 2003, Windows Server 2008 R2 SP1, Windows Server 2008 Service Pack 2, Windows Server 2012, Windows Server 2012 R2, Windows Vista Service Pack 2, Windows XP Service Pack 3
// requires Windows Installer 3.1 or later (??)
// requires Internet Explorer 5.01 or later (??)
// http://www.microsoft.com/downloads/en/details.aspx?FamilyID=9cfb2d51-5ff4-4491-b0e5-b386f32c0992

[CustomMessages]
vcredist2013_title=Visual C++ 2013 Redistributable

en.vcredist2013_size=6.2 MB
de.vcredist2013_size=6,2 MB

en.vcredist2013_size_x64=6.9 MB
de.vcredist2013_size_x64=6,9 MB

;http://www.microsoft.com/globaldev/reference/lcid-all.mspx
en.vcredist2013_lcid=''
de.vcredist2013_lcid='/lcid 1031 '

[Code]
const
    vcredist2013_url = 'http://download.microsoft.com/download/2/E/6/2E61CFA4-993B-4DD4-91DA-3737CD5CD6E3/vcredist_x86.exe';
    vcredist2013_url_x64 = 'http://download.microsoft.com/download/2/E/6/2E61CFA4-993B-4DD4-91DA-3737CD5CD6E3/vcredist_x64.exe';


procedure vcredist2013();
var
    version: cardinal;
begin
    RegQueryDWordValue(HKLM, 'SOFTWARE\Microsoft\VisualStudio\12.0\VC\VCRedist\' + GetString('x86', 'x64',''), 'Installed', version);

    if (version <> 1) then
    AddProduct('vcredist2013' + GetArchitectureString() + '.exe',
            CustomMessage('vcredist2013_lcid') + '/passive /norestart',
            CustomMessage('vcredist2013_title'),
        CustomMessage('vcredist2013_size' + GetArchitectureString()),
            GetString(vcredist2013_url, vcredist2013_url_x64,''),false, false);
end;

Does anyone have a better way of doing this?

Thanks.

Update

Here is the latest version.

// requires Windows 7 Service Pack 1, Windows 8, Windows 8.1, Windows Server 2003, Windows Server 2008 R2 SP1, Windows Server 2008 Service Pack 2, Windows Server 2012, Windows Server 2012 R2, Windows Vista Service Pack 2, Windows XP Service Pack 3
// requires Windows Installer 3.1 or later (??)
// requires Internet Explorer 5.01 or later (??)
// http://www.microsoft.com/downloads/en/details.aspx?FamilyID=9cfb2d51-5ff4-4491-b0e5-b386f32c0992
// Thank you (Martyn) https://allthingsconfigmgr.wordpress.com/2013/12/17/visual-c-redistributables-made-simple/
// http://stackoverflow.com/questions/27582762/inno-setup-for-visual-c-redistributable-package-for-visual-studio-2013
// http://stackoverflow.com/questions/11137424/how-to-make-vcredist-x86-reinstall-only-if-not-yet-installed

[CustomMessages]
vcredist2013_title=Visual C++ 2013 Redistribute (32bit)
vcredist2013_title_x64=Visual C++ 2013 Redistribute (64bit)

en.vcredist2013_size=6.2 MB
de.vcredist2013_size=6,2 MB

en.vcredist2013_size_x64=6.9 MB
de.vcredist2013_size_x64=6,9 MB

;http://www.microsoft.com/globaldev/reference/lcid-all.mspx
en.vcredist2013_lcid=''
de.vcredist2013_lcid='/lcid 1031 '

[Code]
#IFDEF UNICODE
    #DEFINE AW "W"
#ELSE
    #DEFINE AW "A"
#ENDIF
type
    INSTALLSTATE = Longint;
const
    INSTALLSTATE_INVALIDARG = -2;  // An invalid parameter was passed to the function.
    INSTALLSTATE_UNKNOWN = -1;     // The product is neither advertised or installed.
    INSTALLSTATE_ADVERTISED = 1;   // The product is advertised but not installed.
    INSTALLSTATE_ABSENT = 2;       // The product is installed for a different user.
    INSTALLSTATE_DEFAULT = 5;      // The product is installed for the current user.

    //DOWNLOADS FOR VISUAL C++ 2013
    VC_REDIST2013_URL = 'http://download.microsoft.com/download/2/E/6/2E61CFA4-993B-4DD4-91DA-3737CD5CD6E3/vcredist_x86.exe';
    VC_REDIST2013_URL_x64 = 'http://download.microsoft.com/download/2/E/6/2E61CFA4-993B-4DD4-91DA-3737CD5CD6E3/vcredist_x64.exe';

    //OPTIONS
    VC_2013_REDIST = '{13A4EE12-23EA-3371-91EE-EFB36DDFFF3E}'; //Microsoft.VS.VC_RuntimeMinimumVSU_x86,v12
    VC_2013_REDIST_x64 = '{A749D8E6-B613-3BE3-8F5F-045C84EBA29B}'; //Microsoft.VS.VC_RuntimeMinimumVSU_amd64,v12

    function MsiQueryProductState(szProduct: String): INSTALLSTATE;
    external 'MsiQueryProductState{#AW}@msi.dll stdcall';

function VCVersionInstalled(const ProductID: String): Boolean;
begin
    Result := MsiQueryProductState(ProductID) = INSTALLSTATE_DEFAULT;
end;

procedure vcredist2013();
var 
     target_x86_Only: Boolean;
     target_x64_Only: Boolean;
     target_x64x86_Either: Boolean;
begin
     //OPTION SETTINGS ONE TRUE ONLY
     target_x86_Only := True;
     target_x64_Only := False;
     target_x64x86_Either := False;
     //END OPTION SETTINGS


    //Will Install 32 bit only.
    if (target_x86_only = True) then begin
        if NOT VCVersionInstalled(VC_2013_REDIST) then
           AddProduct('vcredist_x86.exe',  
              CustomMessage('vcredist2013_lcid') + '/install /quiet /norestart',
              CustomMessage('vcredist2013_title'),
              CustomMessage('vcredist2013_size'),
              VC_REDIST2013_URL,
                false, false);
     end;      

     //Will attempt to install 64 bit only
     if (target_x64_Only) then begin
         if (IsX64) then begin
            if NOT VCVersionInstalled(VC_2013_REDIST_x64) then
               AddProduct('vcredist_x64.exe',  
                  CustomMessage('vcredist2013_lcid') + '/install /quiet /norestart',
                  CustomMessage('vcredist2013_title_x64'),
                  CustomMessage('vcredist2013_size_x64'),
                  VC_REDIST2013_URL_x64,
                    false, false);
          end else begin
             MsgBox('Sorry Cant install x64 application on x86 machine.', mbInformation, MB_OK); 
          end;
     end; 

     //Will attempt to install x64 and if it's not available it will install the x86 version
     if (target_x64x86_Either) then begin
         if (IsX64) then begin
            if NOT VCVersionInstalled(VC_2013_REDIST_x64) then
               AddProduct('vcredist_x64.exe',  
                  CustomMessage('vcredist2013_lcid') + '/install /quiet /norestart',
                  CustomMessage('vcredist2013_title_x64'),
                  CustomMessage('vcredist2013_size_x64'),
                  VC_REDIST2013_URL_x64,
                    false, false);
          end else begin
              if NOT VCVersionInstalled(VC_2013_REDIST) then
                 AddProduct('vcredist_x86.exe',  
                CustomMessage('vcredist2013_lcid') + '/install /quiet /norestart',
                CustomMessage('vcredist2013_title'),
                CustomMessage('vcredist2013_size'),
                VC_REDIST2013_URL,
                  false, false);
          end;
     end; 
end;
David Eaton
  • 564
  • 2
  • 10
  • 22
  • 1
    Are you sure you're looking at the right registry key? *VisualStudio\12.0\VC\VCRedist\*. Is that the key that would indicate 2013 was installed? If not, it would reinstall every time because you're checking the version from the wrong key. – Ken White Dec 20 '14 at 18:01
  • Opening up regedit it does not look like it's finding that key.... I have been searching for a way to detect it.. The odd part is that the 2010 version seems to work correctly.... from what I can tell.. Or maybe Vista and XP you can detect this way but not windows 7 and up? – David Eaton Dec 20 '14 at 18:11
  • Maybe the question should have been how to detect if Visual C++ Redistributable has been installed ? http://www.eatoncode.com/shareit/2014-12-20_1216.png – David Eaton Dec 20 '14 at 18:20
  • 1
    I've been asked for that for VC Redist 2012 ([`here`](http://stackoverflow.com/questions/11137424/how-to-make-vcredist-x86-reinstall-only-if-not-yet-installed/11172939#comment41008074_11172939) on SO, many times by mail). But the problem is that there's no official list of those product codes, so I've put it to the bottom of my to-do list. – TLama Dec 20 '14 at 18:46
  • Well this maybe usefull.. here are some codes here -> https://allthingsconfigmgr.wordpress.com/2013/12/17/visual-c-redistributables-made-simple/ but the problem is that how do I search for {13A4EE12-23EA-3371-91EE-EFB36DDFFF3E} and {F8CFEB22-A2E7-3971-9EDA-4B11EDEFC185} ? Do I search the entire HLM or is there a uniform place to find these ? Is the CLSID where I should be looking ? http://www.eatoncode.com/shareit/2014-12-20_1302.png – David Eaton Dec 20 '14 at 19:04
  • 1
    Might be so. What's more important is that the list on the site you've linked is the list of MSI product codes. Codes that I've used in the post near the comment I linked. The MSI API should be the right way here, so you just take a product code of your choice and ask the `MsiQueryProductState` function for its state. What this function does in the beackground should not be of your interest ;-) – TLama Dec 21 '14 at 10:43
  • 1
    I'm not using isxdl.dll library in my code. I'm importing just one function from the Windows API library msi.dll, so the problem won't be in my detection code. Could you try to run just the detection part without the downloader part, please ? – TLama Dec 21 '14 at 18:47
  • 1
    One [`hint for DRY`](http://pastebin.com/sLkG1J1V) pattern. – TLama Dec 21 '14 at 21:11
  • Can you modify the code and paste as answer? I deleted my answer... :) – David Eaton Dec 21 '14 at 21:16
  • I don't know from where you call the `vcredist2013` procedure, but I guess that would require me to understand that Modular InnoSetup Dependency Installer (which by its name sounds like some extra terrestrial technology :) It was just a hint of mine since you are repeating parts where you're adding VC redist versions to install (I'm not sure if you could use the code I've linked as a hint literally as it is with that MIDI). Your code looks correct and I believe it should work as it is written. – TLama Dec 21 '14 at 21:48
  • 1
    Ok... I like your idea on how to remove the dry code.... I restored my last answer... i will try to see how I can use your idea... :) – David Eaton Dec 21 '14 at 21:54

1 Answers1

3

@TLama Thanks for all your help on this...

Here is my final version.....

// requires Windows 7 Service Pack 1, Windows 8, Windows 8.1, Windows Server 2003, Windows Server 2008 R2 SP1, Windows Server 2008 Service Pack 2, Windows Server 2012, Windows Server 2012 R2, Windows Vista Service Pack 2, Windows XP Service Pack 3
// requires Windows Installer 3.1 or later (??)
// requires Internet Explorer 5.01 or later (??)
// http://www.microsoft.com/downloads/en/details.aspx?FamilyID=9cfb2d51-5ff4-4491-b0e5-b386f32c0992
// Thank you (Martyn) https://allthingsconfigmgr.wordpress.com/2013/12/17/visual-c-redistributables-made-simple/
// http://stackoverflow.com/questions/27582762/inno-setup-for-visual-c-redistributable-package-for-visual-studio-2013
// http://stackoverflow.com/questions/11137424/how-to-make-vcredist-x86-reinstall-only-if-not-yet-installed

[CustomMessages]
vcredist2013_title=Visual C++ 2013 Redistribute (32bit)
vcredist2013_title_x64=Visual C++ 2013 Redistribute (64bit)

en.vcredist2013_size=6.2 MB
de.vcredist2013_size=6,2 MB

en.vcredist2013_size_x64=6.9 MB
de.vcredist2013_size_x64=6,9 MB

;http://www.microsoft.com/globaldev/reference/lcid-all.mspx
en.vcredist2013_lcid=''
de.vcredist2013_lcid='/lcid 1031 '

[Code]
#IFDEF UNICODE
    #DEFINE AW "W"
#ELSE
    #DEFINE AW "A"
#ENDIF
type
    INSTALLSTATE = Longint;
const
    INSTALLSTATE_INVALIDARG = -2;  // An invalid parameter was passed to the function.
    INSTALLSTATE_UNKNOWN = -1;     // The product is neither advertised or installed.
    INSTALLSTATE_ADVERTISED = 1;   // The product is advertised but not installed.
    INSTALLSTATE_ABSENT = 2;       // The product is installed for a different user.
    INSTALLSTATE_DEFAULT = 5;      // The product is installed for the current user.

    //DOWNLOADS FOR VISUAL C++ 2013
    VC_REDIST2013_URL = 'http://download.microsoft.com/download/2/E/6/2E61CFA4-993B-4DD4-91DA-3737CD5CD6E3/vcredist_x86.exe';
    VC_REDIST2013_URL_x64 = 'http://download.microsoft.com/download/2/E/6/2E61CFA4-993B-4DD4-91DA-3737CD5CD6E3/vcredist_x64.exe';

    //OPTIONS
    VC_2013_REDIST = '{13A4EE12-23EA-3371-91EE-EFB36DDFFF3E}'; //Microsoft.VS.VC_RuntimeMinimumVSU_x86,v12
    VC_2013_REDIST_x64 = '{A749D8E6-B613-3BE3-8F5F-045C84EBA29B}'; //Microsoft.VS.VC_RuntimeMinimumVSU_amd64,v12

    function MsiQueryProductState(szProduct: String): INSTALLSTATE;
    external 'MsiQueryProductState{#AW}@msi.dll stdcall';

function VCVersionInstalled(const ProductID: String): Boolean;
begin
    Result := MsiQueryProductState(ProductID) = INSTALLSTATE_DEFAULT;
end;

procedure vcredist2013();
var 
     target_x86_Only: Boolean;
     target_x64_Only: Boolean;
     target_x64x86_Either: Boolean;
begin
     //OPTION SETTINGS ONE TRUE ONLY
     target_x86_Only := True;
     target_x64_Only := False;
     target_x64x86_Either := False;
     //END OPTION SETTINGS


    //Will Install 32 bit only.
    if (target_x86_only = True) then begin
        if NOT VCVersionInstalled(VC_2013_REDIST) then
           AddProduct('vcredist_x86.exe',  
              CustomMessage('vcredist2013_lcid') + '/install /quiet /norestart',
              CustomMessage('vcredist2013_title'),
              CustomMessage('vcredist2013_size'),
              VC_REDIST2013_URL,
                false, false);
     end;      

     //Will attempt to install 64 bit only
     if (target_x64_Only) then begin
         if (IsX64) then begin
            if NOT VCVersionInstalled(VC_2013_REDIST_x64) then
               AddProduct('vcredist_x64.exe',  
                  CustomMessage('vcredist2013_lcid') + '/install /quiet /norestart',
                  CustomMessage('vcredist2013_title_x64'),
                  CustomMessage('vcredist2013_size_x64'),
                  VC_REDIST2013_URL_x64,
                    false, false);
          end else begin
             MsgBox('Sorry Cant install x64 application on x86 machine.', mbInformation, MB_OK); 
          end;
     end; 

     //Will attempt to install x64 and if it's not available it will install the x86 version
     if (target_x64x86_Either) then begin
         if (IsX64) then begin
            if NOT VCVersionInstalled(VC_2013_REDIST_x64) then
               AddProduct('vcredist_x64.exe',  
                  CustomMessage('vcredist2013_lcid') + '/install /quiet /norestart',
                  CustomMessage('vcredist2013_title_x64'),
                  CustomMessage('vcredist2013_size_x64'),
                  VC_REDIST2013_URL_x64,
                    false, false);
          end else begin
              if NOT VCVersionInstalled(VC_2013_REDIST) then
                 AddProduct('vcredist_x86.exe',  
                CustomMessage('vcredist2013_lcid') + '/install /quiet /norestart',
                CustomMessage('vcredist2013_title'),
                CustomMessage('vcredist2013_size'),
                VC_REDIST2013_URL,
                  false, false);
          end;
     end; 
end;

Hopes this helps some one else.

David Eaton
  • 564
  • 2
  • 10
  • 22
  • 4
    The Author of Modular InnoSetup Dependency Installer (stfx) has updated his collection to include this code above with a little more correctness - http://www.codeproject.com/Articles/20868/NET-Framework-Installer-for-InnoSetup Grab the updated version there. – David Eaton Jan 30 '15 at 17:48