Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Single MSI to install correct 32 or 64 bit c# application

I have a C# application which is built for both x86 (32 bit) and x64 (64 bit) platforms. My build system currently outputs two MSI installers, one for each platform. In case it makes a difference, my C# application includes a windows taskbar toolbar which means that the installed DLL must be loaded by the explorer.exe process.

Is it possible to produce a single MSI installer which will install the correct version of my application depending on whether the current OS is a 64 bit OS?

This has currently been achieved by using http://dotnetinstaller.codeplex.com/ to produce an EXE which performs the architecture check and then launches the correct MSI. However, I would prefer a purely MSI based approach.

like image 357
mchr Avatar asked Sep 16 '10 08:09

mchr


People also ask

Is MSI 32 or 64-bit?

MSI does not support the mixed package type. The EXE file built by Advanced Installer is a 32 bit one, this contains the x86 and x64 MSI files as well as the files to be installed from the CAB.

What means of x64 MSI Installer?

The x64. msi version is the installer for the 64-bit version of Windows, while the x86. msi version is the installer for the default 32-bit version of Windows. From your previous posts, I think you have the standard version, so you wouldn't need the 64-bit version.

Can I install both 32 and 64-bit Windows?

Windows 10 can run on both 32-bit and 64-bit processor architectures. If you have a computer with a 32-bit setup, you can upgrade to the 64-bit version without acquiring a new license. The only caveat is that there is no in-place upgrade path to make the switch.

What is 32bit MSI?

A 32-bit package consists of only 32-bit Windows Installer components and must have the value "Intel" entered in the platform field of the Template Summary Property. For more information, see Windows Installer on 64-bit Operating Systems and 64-bit Windows Installer Packages.


2 Answers

You could work around the problem. Pack the 2 installers under third deployment project. Create a custom action that checks the running OS version, then make the installer call the right installer.

Something like this:

[RunInstaller(true)]
public partial class MyInstaller: Installer
{
    String installerPath;

    public MyInstaller()
    {
        InitializeComponent();       
        if (Is64Bit())//running as 64-bit
        {
            installerPath= @"installfolder\my64bitsetup.exe";
        }
        else
        {
            installerPath= @"installfolder\my32bitsetup.exe";
        }
    }

    [SecurityPermission(SecurityAction.Demand)]
    public override void Install(IDictionary stateSaver)
    {
        base.Install(stateSaver);
    }

    [SecurityPermission(SecurityAction.Demand)]
    public override void Commit(IDictionary savedState)
    {
        base.Commit(savedState);
        MyInstall();
    }

    [SecurityPermission(SecurityAction.Demand)]
    public override void Rollback(IDictionary savedState)
    {
        base.Rollback(savedState);
    }

    [SecurityPermission(SecurityAction.Demand)]
    public override void Uninstall(IDictionary savedState)
    {
        base.Uninstall(savedState);
        base.Commit(savedState);
    }

    private void MyInstall()
    {
         ProcessStartInfo procStartInfo = new ProcessStartInfo("cmd.exe", "/c " + installerPath);
        RunProcess(procStartInfo);
    }

    private void RunProcess(ProcessStartInfo procStartInfo)
    {
        Process proc = new Process();
        proc.StartInfo = procStartInfo;
        proc.Start();
        proc.WaitForExit();
    }

[DllImport("kernel32.dll", SetLastError = true, CallingConvention = CallingConvention.Winapi)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool IsWow64Process([In] IntPtr hProcess, [Out] out bool lpSystemInfo);

private bool Is64Bit()
{
    return (IntPtr.Size == 8 || (IntPtr.Size == 4 && Is32BitProcessOn64BitProcessor()));
}

private bool Is32BitProcessOn64BitProcessor()
{
    bool retVal;
    IsWow64Process(Process.GetCurrentProcess().Handle, out retVal);
    return retVal;
}

Ok, that was long...

Anyway, in the Commit you can be sure that the installers are already unpacked, just make sure you have the right path. (You can change the cmd command from /c to /k for testings, that will keep the command prompt window alive for you to see the messages)

You can read some more about custom actions, the installation path can be passed by arguments.

like image 100
Yochai Timmer Avatar answered Oct 05 '22 08:10

Yochai Timmer


No, this is not possible. See Heath Stewart's Different Packages are Required for Different Processor Architectures post. The only way to handle this with MSI is with a bootstrap along the lines of what you describe. If you just needed to put a file or key or two in a 64-bit location, it's possible (but not recommended) to do that in a custom action, but changing the target installation location and using built-in MSI file support won't work.

like image 39
Michael Urman Avatar answered Oct 05 '22 10:10

Michael Urman