Tuesday, October 30, 2012

Installing 64-bit drivers from 32-bit installer

If you are using a 32-bit Windows installer, it is not straightforward to have it install a 64-bit driver. There are at least two reasons why you might be in this situation:
  1. Your installer software is not the latest (or maybe doesn't even have a 64-bit version yet) ... or ...
  2. Most of your components are 32-bit with just one or two that you want to differentiate 32 vs 64 bit.
The problem arises because shelling out to msiexec.exe from a 32-bit installer (and in the case of InstallShield, whether that be from InstallScript or as a Custom Action), the 32-bit C:\Windows\SysWOW64\msiexec.exe gets executed instead of the 64-bit C:\Windows\System32\msiexec.exe.

The basic answer comes from technet and the VB.Net code below is adapted from that with a slight improvement. By compiling the VB.Net code into an executable and shelling to that as an intermediary, the 32-bit world can be escaped from. The slight improvement to the code below is it preserves quotes around quoted arguments such as pathnames with spaces.

Module Module1
    Sub Main()
    Dim arrArgs As Array
    Dim Args As String = ""
    Dim intCount As Integer = 0

    arrArgs = System.Environment.GetCommandLineArgs()
    For Each Arg In arrArgs
        If intCount <> 0 Then
            If Arg.IndexOf(" ") > -1 Then
                Args = Args & " """ & Arg & """"
            Else
                Args = Args & " " & Arg
            End If
        End If
        intCount = intCount + 1
    Next
    Shell("cmd.exe /C" & Args, AppWinStyle.NormalFocus, True)
    End Sub
End Module

Then the InstallScript to invoke it is below.  It detects whether the OS is 64-bit, and if so installs the 64-bit drivers via the VB.Net code above (which is compiled to an executable cmd64.exe); otherwise, it installs the 32-bit drivers.

if ( REMOVEALLMODE=0 ) then
    if (Is(FILE_EXISTS, WINSYSDIR^"CsSsm.dll") = FALSE) then
        if (SYSINFO.bIsWow64) then
            svProgramCmd64 = TARGETDIR^"GaGe64\\cmd64.exe";
            svCmd64MsiExecPath = WINSYSDIR64^"msiexec.exe";
            LongPathToQuote(svCmd64MsiExecPath,TRUE);
            svCmd64MsiPath = TARGETDIR^"GaGe64\\CompuScope.msi";
            LongPathToQuote(svCmd64MsiPath,TRUE);
            svCmd64Param = svCmd64MsiExecPath + " /i " +

                           svCmd64MsiPath + " /passive /norestart";
            LaunchAppAndWait(svProgramCmd64,svCmd64Param,WAIT);
        else
            svProgramMsiExec = WINSYSDIR^"msiexec.exe";
            svGaGe32MsiPath = TARGETDIR^"GaGe32\\CompuScope.msi";
            LongPathToQuote(svGaGe32MsiPath,TRUE);
            svGaGe32Param = "/i " + svGaGe32MsiPath +

                            " /passive /norestart";
            LaunchAppAndWait(svProgramMsiExec,svGaGe32Param,WAIT);
        endif;
    endif;

endif;
The code above is for installing drivers for a GaGe CompuScope analog-to-digital converter board.  I am a user of GaGe boards, not an employee or representative of GaGe.

No comments: