经过太多实验,我得出结论,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.
没有意义。
答案 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
(我几乎总是在InstallInitialize
和InstallFinalize
之间的某处运行
<InstallExecuteSequence>
<Custom Action="EXECA_CALLMYEXE" After="InstallInitialize"><![CDATA[Not REMOVE]]></Custom>
$$$:获取InstallShield (HERE)
首先创建一个“基本MSI”项目,并确保你说你想要没有生成setup.exe 。您可以在发布设置中设置它。
然后你基本上做与WiX相同的事情,但你有一个用户界面。
InstallExecuteSequence
和InstallInitialize
之间的某个位置来插入自定义操作。抱歉,我不能更详细,但这应该是一个好的开始。
答案 1 :(得分:6)
答案 2 :(得分:4)
安装程序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)
简单的技巧:
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
答案 12 :(得分:-2)
Nah man,只需使用Inno Setup的向导。它设置EXE而不是MSI。这就像5分钟,你将有一个Windows安装程序。
只需download,安装它,将其指向您的EXE,然后按照屏幕上的提示进行操作