How to install 2nd .exe in Wix InstallExecuteSequence with the 2nd one only occurring after the first one finishes? - wix3.5

I am creating my first .msi installer using WiX 3.5 setup project in vs2015.
I have 2 <CustomAction> defined in my .wxs page, they are both .exe files.
The First .exe file executes fine as it waits for the After="InstallFinalize" state.
However the first .exe actually does a job that downloads another .zip file from the web which contains our 2nd .exe.
I need to complete the 2nd Custom Action after the first .exe finishes exploding the package. I have tested both custom actions independently and both will install.
<Custom Action="LaunchInstallSoftwareAutoUpdaterProcessAction" After="InstallFinalize" />
<Custom Action="LaunchSoftwareAutoUpdaterProcessAction" After="InstallFinalize">NOT Installed AND NOT REMOVE</Custom>
I am new to WiX but I do not think there is another way to wait that I am aware of. How can I accomplish this?

Related

WiX running batch file, before file copy

I am Using WiX 3.5 for making installer, i need to copy many files and folder.
I used heat.exe to do that, and it is working fine.
But i need to call bat file during installation, and the bat file is present in those folders i mentioned above. That bat file is depended on some other files.
I am able to call the batch file but by that time the other files are not loaded.
Below is the custom action i am using for running bat file.
<Custom Action="InstallFeature" After="InstallFinalize"><![CDATA[
(&TypicalFeature=3) AND NOT(!TypicalFeature=3)
]]></Custom>
Need help, may be files are loading after i call the bat file.
Thanks
Ravi S
Calling a batch file from an MSI is a really really bad idea. MSI is declarative - you simply define what the system should look like on a successful installation, if something goes wrong, MSI can roll back the changes.
However by using a batch file, Windows Installer doesn't know what changes were made to the system and can't roll anything back.
I would look into what the batch file is doing, and implement what it is doing either in WiX, or via a custom action in C++/C# with corresponding rollback action. (Native code is best, but it's hard. Managed code is the next best thing and VBScript is a last resort - but still better than a batch file)

Wix - remove all files when apply major special update

In previous version of installer, created by Wix, next code exists:
<InstallExecuteSequence>
<RemoveExistingProducts After="InstallInitialize" />
</InstallExecuteSequence>
In order to work around the bug in Windows Installer described in this knowledge base article code has been fixed:
<InstallExecuteSequence>
<RemoveExistingProducts After="InstallFinalize" />
</InstallExecuteSequence>
But now, if I install program with installer with first code and then install program with installer with second code without remove installed program, all files remove and my path exist empty folders (all files in both installer have equal name).
If I open second installer and press Repair - all files appear.
What wrong and how this problem fix?
P.S. Sorry for my English :(
Just a guess: It sounds like the first and the second setup install the same files but as part of components with different component id's. To verify this, you can open both msi files with orca.exe and compare the component ids.
The component IDs should stay the same, so that they can be properly reference counted. Otherwise you will get different components trying to manage the same files, which will in this case result in disappearing files when either of the components is uninstalled.
If you follow the windows installer rule that the content of a component should never change (i.e. never remove or add files to it) then the component GUIDs generated by wix should automatically stay stable. This is one of the reasons why it is best to have one component per file.

Visual Studio Project to install multiple executables with one installer

I have 3 driver installers (.exe). I need to wrap them up in a single installer app so that my users can run one executable which then installs the 3 drivers.
In visual studio 2010, what is the best way to do this?
EDIT: I don't want the three executables to remain on the machine once the install is finished.
What I did to solve this problem was to put my multiple exe's into a self-extracting zip file and set the PostExtractCommandLine to a separate "installer" exe, which in turn checked for requirements, installed necessary components, restarted when needed, and installed my original exe's. This does however leave behind all the files, though you can have the "installer" exe delete everything when it's done.
(I used a library called DotNetZip to make the SFX.)
Edit
I had two applications I wanted to install, App1 and App2. These were both msi setup projects and could be installed separately. I then created AppsInstaller.exe, which ran App1.msi and App2.msi by calling msiexec /i C:\\Install\\App1.msi /qn, etc, as well as doing some other work. All three programs were put into an SFX file, with AppsInstaller.exe as the PostExtractCommandLine. My AppsInstaller.exe did everything silently, so no wizards where present, and is why I used msiexec. Since you want the wizard to show you can just call the msi's as Process's and use a WaitForExit to keep it coming one at a time.

GAC an assembly without embedding it within the MSI

I want to GAC an assembly already present on target machines, I know where this assembly is on every machine (you can assume, that path is static for all target machines and wont change and that I am the owner of this assembly) I do not want to include the assembly to be GAC'd in the MSI since it can change with each solution deployment and we dont want our setup to be modified each time. I tried using the <File> tag with Assembly =".net"
<File
Id="Assembly.dll"
Name="Assembly.dll"
Assembly=".net"
Source="Assembly.dll"
KeyPath="yes" >
</File>
but using File embeds my assembly in the MSI. Any ideas on how to just tell the MSI to just look for the assembly in a particular location and not include it?
That's not supported by the Windows Installer. It isn't immediately clear why you would want to take someone else's file and put into the GAC (if it was your file, why not put it in the GAC to begin with?). :)
Seems like an odd request, but the way to do this would be to write a script / batch file to GAC the file. Test this out by itself without the MSI. Once working, include the script in the MSI, and then execute the script as a custom action to execute on install. You would also want to remove it from the GAC on uninstall.
If you are using a Visual Studio setup project, right click on the project, and choose View->Custom Actions. From there it will let you add the actions for the appropriate events (install, uninstall, etc).

How to make an MSI that simply wraps an EXE file

After way too many experiments, I've come to the conclusion that Windows Installer is simply bad technology. But the customers want MSI files.
So, how can I create an MSI file that extracts an EXE file to a temporary directory and runs it with options same or similar as were passed to the EXE file?
Options to an MSI are explained in Msiexec (command-line options) (low level "run" of an MSI is msiexec option package.msi).
EDIT: mjmarsh's WiX solution looks like it works. I just haven't had a chance to try it yet (crunch time). If it works, I'll be accepting it.
EDIT: it does not work. Missing piece: attended/unattended does not seem to be available.
Anyway, the only to make this work at all would be for the custom action to kill its parent process!
EDIT: So somebody posted as a further answer wrapping the whole thing as a post-install custom action. Theoretically possible but since a reboot may be required (thanks MS for .NET 4 requiring a reboot sometimes) we have to do further hackery. So from the matrix of advantages:
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.
No point.
Well, there is the free way and the $$$ way. I cannot document everything here, but this should get you started.
On a side note, yes, Windows Installer is a maddening technology. There are many times where I think a task will be straightforward, but it actually becomes complicated. You definitely have to immerse yourself to understand it.
In any case, here goes:
Free: WiX (here)
This is a free tool to generate MSI files from a set of XML configuration files. I'll leave you to find tutorials online, but here is the crux:
You can compress your EXE into the installer by using the following tag in the WXS file:
<Binary Id="MYEXE" src="<path to my exe?"/>
Then you can create a custom action which launches your EXE file:
<CustomAction Id="EXECA_CALLMYEXE" Return="check" Execute="deferred" BinaryKey="MYEXE"
ExeCommand="my command line"/>
Then you insert your custom action into the InstallExecuteSequence in the appropriate spot (I almost always run mine somewhere between InstallInitialize and InstallFinalize)
<InstallExecuteSequence>
<Custom Action="EXECA_CALLMYEXE" After="InstallInitialize"><![CDATA[Not REMOVE]]></Custom>
$$$: Get InstallShield (HERE)
First create a "Basic MSI" project and make sure you say you want no setup.exe generated. You set this in the Release settings.
Then you essentially do the same thing as with WiX, but you have a UI for it.
You can specify your helper EXE file by using the Direct Editor and putting your EXE file in the 'Binary' table
You can create a custom action to launch that EXE file from the "Custom Actions" Node in the tree on the left
You can insert the custom action by selecting "Install Sequences" and putting it in the InstallExecuteSequence somewhere between InstallInitialize and InstallFinalize as I said before.
Sorry, I could not be more detailed, but this should be a good start.
I think the easiest way to create a .MSI file is to use WiX.
Lesson 1 from the WiX tutorial is all you need to create a simple install.
Joshua, I understand your frustration very well. MSI is quirky to say the least - a completely new way to think of deployment. Still, applied correctly MSI offers the best possible deployment, especially for corporate customers.
What operations does your installer EXE perform? Is it largely file copy, some COM registration and some registry writes, or does it run complex installation logic, setting up databases etc...? The reason I ask is because it probably would be very quick to create a well functioning WIX MSI for you so you can abandon the EXE approach.
It is indeed possible to run an EXE from inside an MSI, but it requires proper sequencing, and it is guaranteed to cause you more blues than a simple MSI. If the app is small, and not doing anything crazy during installation, I would be happy to provide you with a basic WIX conversion.
A summary of deployment tools and their strengths and weaknesses
Advantages of using MSI files
Adding to weir's answer, change the custom action attribute like below:
<!--Run Action-->
<CustomAction Id="RunWrappedExe"
Return="asyncNoWait"
FileKey="ApplicationFileId"
Execute="deferred"
ExeCommand=""
HideTarget="no"
Impersonate="yes"/>
Setting Return=asyncNoWai does not wait for the exe to return. The installer does it's job and closes normally. Meanwhile, the exe continous its execution.
-Madhuresh
No solution. We went NSIS as corporate MSI install is going to be broken anyway due to MSI nesting problem (just try installing EXE wrapping MSI from inside MSI someday).
If you don't want to manage MSI, but only execute EXE, try Exe to MSI Converter Free. You just put in the path to the EXE and get an MSI.
There is also a free version of the MSI Wrapper. It also supports uninstall and upgrades. Also, it only creates one entry in the Add or Remove programs.
try this:
In MSI package, there is a behaviour call "Launch an application after installation", that means your exe file will be executed after the MSI installation(the MSI is closed).
Try to execute your exe there, so when your exe invoke other MSI packages, it won't conflict with the first one.
Wix can do it. Here is my sample code for 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>
I was having the same problem (wrap EXE, call other MSI from the EXE including .net setup, etc.),
and here is my solution:
I build the setup exe using InstallAware.
It has its own MSI Wrapper that wraps the generated EXE with MSI.
It works OK, the EXE can call other MSIs without any problem (including .net setup, other 3rd party setups), but that is because the launching MSI ends ("returns") rights after it launches the setup EXE file, and that way they avoid the MSI limitation of recursive MSI calls.
BUT - some customers (companies) that uses MSI deployment tools, requires the MSI (msiexec) to return (end) only after the setup process ends, and that is a problem with the above solution.
So - to solve this:
There is another MSI Wrapper (exemsi.com) that generates MSI that returns only after the EXE setup ends, but for using that you must use another unique option of InstallAware:
InstallAware has the option to generate the EXE setup using their own native engine, and not based on Windows Installer engine, to avoid MSI recursive limitation.
Combine those both, and you have the perfect solution.
Hope this will help someone, although many years passed since this question was first posted.
Simple trick:
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);
}
}
}
Nah man, just use Inno Setup's wizard. It makes an setup EXE but not an MSI. It's like 5 mins and you'll have a windows installer.
Simply download it, install it, point it to your EXE, and follow the on-screen prompts

Resources