5
votes

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;
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
I've been asked for that for VC Redist 2012 (here 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
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
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
One hint for DRY pattern.TLama

1 Answers

3
votes

@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.