如何制作一个简单包装EXE文件的MSI

时间:2009-05-12 21:06:25

标签: installer windows-installer msiexec

经过太多实验,我得出结论,Windows Installer简直就是糟糕的技术。但客户需要MSI文件。

那么,我如何创建一个MSI文件,将EXE文件提取到临时目录并使用与传递给EXE文件相同或相似的选项运行它?

MSI的选项在 Msiexec (command-line options) 中解释(MSI的低级“运行”是msiexec选项package.msi)。

编辑:mjmarsh的WiX解决方案看起来很有效。我还没有机会尝试它(关键时刻)。如果它有效,我会接受它。

编辑:它不起作用。遗失的部分:有人/无人看管似乎没有。

无论如何,唯一可以完成这项工作的是自定义操作来杀死它的父进程!

编辑:所以有人发布了一个进一步的答案,将整个事情包装成安装后的自定义操作。理论上可行,但由于可能需要重新启动(感谢MS for .NET 4有时需要重新启动),我们必须做进一步的hackery。所以从优势矩阵:

Transparency: No. One big custom action.
Customizability: No.
Standardization: No. 
Management and reporting: No. Appears to work but will not.
Security: No benefit.
Validation: No. The hackery required to survive reboot makes this sure to not work.
Resiliency: Completely defeated.
Rollback: No. Rollback didn't work when we were using MSI anyway.
Patching & Updates: No. We have a local solution anyway.
Logging: No. Appears to work but will not.

没有意义。

13 个答案:

答案 0 :(得分:15)

嗯,有免费的方式和$$$方式。我不能在这里记录所有内容,但这应该让你开始。

另一方面,是的,Windows Installer是一项令人抓狂的技术。有很多次我认为任务很简单,但实际上它变得复杂了。你必须让自己沉浸在理解中。

无论如何,这里是:

免费:WiX here

这是一个从一组XML配置文件生成MSI文件的免费工具。我会让你在网上找到教程,但这里有关键:

您可以使用WXS文件中的以下标记将EXE压缩到安装程序中:

<Binary Id="MYEXE" src="<path to my exe?"/>

然后,您可以创建一个启动EXE文件的自定义操作:

<CustomAction Id="EXECA_CALLMYEXE" Return="check" Execute="deferred" BinaryKey="MYEXE"
      ExeCommand="my command line"/>

然后您将自定义操作插入适当位置的InstallExecuteSequence(我几乎总是在InstallInitializeInstallFinalize之间的某处运行

<InstallExecuteSequence>
   <Custom Action="EXECA_CALLMYEXE" After="InstallInitialize"><![CDATA[Not REMOVE]]></Custom>

$$$:获取InstallShield HERE

首先创建一个“基本MSI”项目,并确保你说你想要没有生成setup.exe 。您可以在发布设置中设置它。

然后你基本上做与WiX相同的事情,但你有一个用户界面。

  • 您可以使用直接编辑器指定助手EXE文件,并将EXE文件放在“二进制”表格中
  • 您可以创建自定义操作以从左侧树中的“自定义操作”节点启动该EXE文件
  • 如前所述,您可以选择“安装序列”并将其放在InstallExecuteSequenceInstallInitialize之间的某个位置来插入自定义操作。

抱歉,我不能更详细,但这应该是一个好的开始。

答案 1 :(得分:6)

我认为创建.MSI文件最简单的方法是使用WiX

来自WiX教程的

Lesson 1就是创建简单安装所需的全部内容。

答案 2 :(得分:4)

约书亚,我非常理解你的沮丧。 MSI至少可以说是一种古怪 - 一种全新的部署思路。仍然,正确应用MSI提供了最佳的部署,特别是对于企业客户。

安装程序EXE执行哪些操作?它主要是文件复制,一些COM注册和一些注册表写入,还是运行复杂的安装逻辑,设置数据库等......?我问的原因是因为它可能会非常快速地为您创建一个运行良好的WIX MSI,因此您可以放弃EXE方法。

确实可以从MSI内部运行EXE,但它需要正确的排序,并且保证比简单的MSI更让你失望。如果应用程序很小,并且在安装过程中没有做任何疯狂的事情,我很乐意为您提供基本的WIX转换。

答案 3 :(得分:2)

没有解决方案。我们去了NSIS,因为MSI嵌套问题导致企业MSI安装无论如何都要破坏(只需尝试有一天从MSI内部安装EXE包装MSI)。

答案 4 :(得分:2)

还有free version of the MSI Wrapper。它还支持卸载和升级。此外,它只在“添加或删除”程序中创建一个条目。

答案 5 :(得分:2)

添加到weir's回答,更改custom action attribute,如下所示:

<!--Run Action-->
    <CustomAction Id="RunWrappedExe"
                  Return="asyncNoWait"
                  FileKey="ApplicationFileId"
                  Execute="deferred"
                  ExeCommand=""
                  HideTarget="no"
                  Impersonate="yes"/>

设置Return=asyncNoWai不会等待exe返回。安装程序完成它的工作并正常关闭。同时,exe继续执行。

-Madhuresh

答案 6 :(得分:1)

Wix可以做到。这是我的wix 3.5示例代码:

<?xml version='1.0'?>
<Wix xmlns='http://schemas.microsoft.com/wix/2006/wi'>
   <Product Id='*' UpgradeCode="11111111-2222-3333-4444-555555555555" 
        Name='My Setup' Language='1033' Version='1.0.0.0' 
        Manufacturer='Your company'>

    <Package Description='pak' InstallerVersion='200' Compressed='yes' />

    <Media Id='1' Cabinet='setup.cab' EmbedCab='yes' />

    <Directory Id='TARGETDIR' Name='SourceDir'>
        <Directory Id="TempFolder">
            <Directory Id="INSTALLLOCATION" Name="~_tmpdir">
                <Component Id='MyComponent' DiskId='1' Guid=''>
                    <File Id="File0" Name="setup.exe" Source="setup.exe" />
                    <File Id="File1" Name="file1.txt" Source="file1.txt" />
                </Component>
            </Directory>
        </Directory>
    </Directory>

    <Feature Id='InstallFeature' Title='Install Feature' Level='1'>
        <ComponentRef Id='MyComponent' />
    </Feature>

    <!-- Run Action -->
    <CustomAction Id="RunWrapExe" Return="ignore" Execute="deferred" 
                  FileKey="File0" ExeCommand="setup.exe param here"  
                  HideTarget="no" Impersonate="no" />

    <InstallExecuteSequence>
        <Custom Action="RunWrapExe" 
                After="InstallFiles">NOT REMOVE~="ALL"</Custom>
    </InstallExecuteSequence>

   </Product>
</Wix>

答案 7 :(得分:1)

如果您不想管理MSI,但只执行EXE,请尝试Exe to MSI Converter Free。您只需输入EXE的路径并获得MSI。

答案 8 :(得分:1)

试试这个:

在MSI包中,有一个行为调用&#34;安装后启动应用程序&#34;,这意味着你的exe文件将在安装MSI后执行(MSI关闭)。

尝试在那里执行你的exe,所以当你的exe调用其他MSI包时,它不会与第一个包冲突。

答案 9 :(得分:0)

我遇到了同样的问题(包装EXE,从EXE调用其他MSI,包括.net设置等), 这是我的解决方案:

我使用InstallAware构建setup exe。 它有自己的MSI Wrapper,用MSI封装生成的EXE。

它工作正常,EXE可以毫无问题地调用其他MSI(包括.net设置,其他第三方设置),但这是因为启动MSI在启动后结束(&#34;返回&#34;)权限设置EXE文件,这样他们就可以避免递归MSI调用的MSI限制。

但是 - 一些使用MSI部署工具的客户(公司)要求MSI(msiexec)仅在设置过程结束后返回(结束),这是上述解决方案的问题。

所以 - 解决这个问题:

还有另一个MSI Wrapper(exemsi.com)生成只在EXE设置结束后才返回的MSI,但是为了使用它,你必须使用另一个独特的InstallAware选项:

InstallAware可以选择使用自己的本机引擎生成EXE设置,而不是基于Windows Installer引擎,以避免MSI递归限制。 结合这两者,你就拥有了完美的解决方案。

希望这会对某人有所帮助,尽管自这个问题首次发布以来已过去很多年。

答案 10 :(得分:-1)

简单的技巧:

Project image

using System;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Runtime.InteropServices;

namespace Setup
{
    internal class Program
    {
        [DllImport("kernel32.dll")]
        private static extern IntPtr GetConsoleWindow();

        [DllImport("user32.dll")]
        private static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);

        private static void Main(string[] args)
        {
            ShowWindow(GetConsoleWindow(), 0);
            Stream st = Assembly.GetExecutingAssembly().GetManifestResourceStream("Setup.MSI.Temp.msi");
            string path = Path.Combine(System.IO.Path.GetTempPath(), "Temp.msi");
            using (var fileStream = new FileStream(path, FileMode.Create, FileAccess.Write))
            {
                st.CopyTo(fileStream);
            }
            Process p = new Process();
            p.StartInfo.FileName = path;
            p.Start();
            p.WaitForExit();
            File.Delete(path);
        }
    }
}

答案 11 :(得分:-1)

我制作了一个简单且免费的.NET工具,用于从exe或文件夹创建MSI(使用wixsharp和wix) http://legacy.averbouch.biz/free-msi-wrapper

screenshot

答案 12 :(得分:-2)

Nah man,只需使用Inno Setup的向导。它设置EXE而不是MSI。这就像5分钟,你将有一个Windows安装程序。

只需download,安装它,将其指向您的EXE,然后按照屏幕上的提示进行操作