单个 MSI 安装正确的 32 或 64 位 C# 应用程序

发布于 2024-09-19 19:30:52 字数 390 浏览 0 评论 0原文

我有一个为 x86(32 位)和 x64(64 位)平台构建的 C# 应用程序。我的构建系统当前输出​​两个 MSI 安装程序,每个平台一个。为了以防万一,我的 C# 应用程序包含一个 Windows 任务栏工具栏,这意味着安装的 DLL 必须由 explorer.exe 进程加载。

是否可以生成一个 MSI 安装程序,根据当前操作系统是否为 64 位操作系统来安装我的应用程序的正确版本?

目前,这已通过使用 http://dotnetinstaller.codeplex.com/ 生成执行以下操作的 EXE 来实现:架构检查,然后启动正确的 MSI。然而,我更喜欢纯粹基于 MSI 的方法。

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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

七月上 2024-09-26 19:30:52

不,这是不可能的。请参阅 Heath Stewart 的 不同的包需要不同的包处理器架构帖子。使用 MSI 处理此问题的唯一方法是按照您所描述的方式使用引导程序。如果您只需要将一个或两个文件或密钥放入 64 位位置,则可以(但不建议)在自定义操作中执行此操作,但更改目标安装位置并使用内置 MSI 文件支持将不会出现问题。不工作。

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.

江南月 2024-09-26 19:30:52

你可以解决这个问题。将 2 个安装程序打包到第三个部署项目下。创建一个自定义操作来检查正在运行的操作系统版本,然后让安装程序调用正确的安装程序。

像这样的事情:

[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;
}

好的,那很长......

无论如何,在提交中您可以确定安装程序已经解压,只需确保您有正确的路径即可。 (您可以将 cmd 命令从 /c 更改为 /k 进行测试,这将使命令提示符窗口保持活动状态以便您查看消息)

您可以阅读有关自定义操作的更多信息,安装路径可以通过参数传递。

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文