Background information:
We used to have a Visual Studio 2010 based installer project, but our install situation got a lot more complicated, and with the projects going away anyway in 2012, we figured we'd start learning WiX / InstallShield LE.
The Problem:
InstallShield LE seems far too limited in the MSI files it creates to fit our needs -- (example, if you check the Office 2007 prerequisite, even though the error says you need "Office 2007 or later" it will fail if you have Office 2010 installed instead -- you can check one or the other, but you can't create an OR condition -- there's a lot more that's just the tip of the iceberg). -- The bootstrapper it creates, on the other hand, is super awesome!
WiX, on the other hand, worked great for making our MSI, but the Burn Bootstrapper has been just one headache after another -- we finally got it working -- but now on our clients' boxes, it's not only failing to elevate when it launches the MSI file, but it's getting detected as a virus by Symantec SONAR and the install is being blocked anyway! (This doesn't happen with InstallShield LE, and code signing certificates are too cost prohibitive for this project.) Honestly, I'd love to just NOT use the Burn Bootstrapper.
The Question:
What alternatives to the WiX Burn Bootstrapper are there? Could the InstallShield LE one be used? What about NSIS? (Does it integrate with Visual Studio 2010/Visual Studio 2012 at all?) -- I'm hoping to do web installs of our prerequisites to keep the installer file size down -- and yes, I have to maintain the .MSI as well (otherwise, I would just switch to full-on NSIS at this point).
Resolution:
While I couldn't make Christopher Painter's solution work, I marked it as the answer because I believe it is the best approach suggested. I went with a pretty evil little hack of a solution, but if you can make Christopher's approach work, I think that's the way to go. If you can't, maybe my hack will get you unstuck.
For around $2K you could upgrade to InstallShield Professional. However, if you are mostly happy with ISLE and can live with only having 1 feature and no customizations of the UI, I can solve the problem regarding Launch Conditions for you.
See my blog article:
Augmenting InstallShield using Windows Installer XML - Certificates
The concept is you author a WiX merge module that searches for the two office versions and schedule an Error custom action (MSI Type 19) that uses the two searches in a logical or condition. Add that to your ISLE project and you've just "blended" the two technologies.
Professional also gives you the PRQ (XML prereq file) editor. Then again throwing the 30 day eval on a VM can get you the same result.
Here is the WXS side of it:
<?xml version="1.0" encoding="utf-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
<Module Id="ISWIX.REQUIRE.MSOFFICE20102013" Language="1033" Version="1.0.0.0">
<Package Id="10ed24f2-6c07-4066-9f39-ba9f66c2667b" Manufacturer="ISWIX, LLC" InstallerVersion="200" />
<Directory Id="TARGETDIR" Name="SourceDir">
<Directory Id="MergeRedirectFolder"/>
</Directory>
<Property Id="OFFICE2010FOUND">
<RegistrySearch Id="findOffice2010" Root="HKLM" Key="SOFTWARE\Microsoft\Office\14.0\Common\InstallRoot" Name="Path" Type="raw" />
</Property>
<Property Id="OFFICE2010X64FOUND">
<RegistrySearch Id="findOffice2010X64" Root="HKLM" Key="SOFTWARE\Microsoft\Office\14.0\Common\InstallRoot" Name="Path" Type="raw" Win64="yes" />
</Property>
<Property Id="OFFICE2013FOUND">
<RegistrySearch Id="findOffice2013" Root="HKLM" Key="SOFTWARE\Microsoft\Office\15.0\Common\ProductVersion" Name="LastProduct" Type="raw" />
</Property>
<CustomAction Id="ErrorNoOffice20102013" Error="[ProductName] setup requires Microsoft Office 2010 or 2013." />
<InstallUISequence>
<Custom Action="ErrorNoOffice20102013" After="AppSearch">Not OFFICE2010FOUND and Not OFFICE2010X64FOUND and Not OFFICE2013FOUND and Not Installed</Custom>
</InstallUISequence>
<InstallExecuteSequence>
<Custom Action="ErrorNoOffice20102013" After="AppSearch">Not OFFICE2010FOUND and Not OFFICE2010X64FOUND and Not OFFICE2013FOUND and Not Installed</Custom>
</InstallExecuteSequence>
</Module>
</Wix>
I'd like to get all the issues you raised about Burn fixed. If you could file bugs on the issues, that would be very helpful.
In the meantime, if you're using WiX toolset v3.5+ you might look at setupbld.exe. That tool can create a tiny pre-req installer that launches a pre-req and then a single MSI.
Note: our goal in the WiX toolset is to ultimately subsume what that tool does with Burn so bug reports where Burn does not work are much appreciated.
In the end Install Shield LE ended up being too much of a headache for me, what I ended up doing was creating an old school 2010 dummy .vdproj based setup project with the correct prerequisites (Windows Installer 3.1, .NET 4.0, and VSTO 2010).
I built it once, and stole the setup.exe (I made sure other things like the upgrade code, etc. matched my current WiX based .msi file -- and the that .msi it generates was the same name I wanted to use, etc).
I package that setup.exe up with my WiX based .msi file and everything works great -- it's definitely a huge hack -- but it's the only solution I could find that both works out of the box(-ish), and does not set off Symantec SONAR anti-virus.
I do not build the .vdproj every time (I've only built it once, I deleted the .msi file, and harvested the setup.exe), so there is no future dependency on Visual Studio 2010 going this route.
For a less hacky approach, see #Christopher Painter's answer -- if you can make his approach work for you, I recommend his approach over mine.
NSIS can be integrated with Visual Studio (2005/2008/2010 and 2012) by an addon called Visual & Installer. Inno Setup is supported too. If you are looking for simple and cheap solution go for this (both NSIS and Inno Setup are freeware systems with huge community around.)
I don't have any experience with WiX, but NSIS and Inno Setup cannot create MSI files(s), only EXE file(s).
Related
Following this basic tutorial I have created a Windows Form App (.NET Core) project in C# called MyApplication, and to the same solution, I added a Setup Project for WiX v3 called MySetup, both named as prescribed by the aforementioned tutorial. I am using Visual Studio 2019. I added the Windows Form App to the References node in the Solution Explorer, and as described by the linked tutorial, I added <File Source="$(var.MyApplication.TargetPath)" /> as shown below, to Product.wxs.
<Fragment>
<ComponentGroup Id="ProductComponents" Directory="INSTALLFOLDER">
<Component Id="ProductComponent">
<File Source="$(var.MyApplication.TargetPath)" />
</Component>
</ComponentGroup>
</Fragment>
When I build the Wix v3 project, I get an msi file. When I run this, it produces a dll file from my form application in the intended directory (Program Files (x86)\MySetup as per the instructions). This is nice, but I want an exe file so I can run the application from the installation directory.
Reading this article, I guessed that the macro $(var.MyApplication.TargetPath) was the issue, but I was not able to find a way to change this. So, I tried to see what happened when I substituted this segment for the full path of the exe file (\MyApplication\bin\Debug\netcoreapp3.0\MyApplication.exe). Rebuilding and rerunning the msi file again, this successfully put the exe file in the desired location. However, when opening this exe, the Windows Form doesn't even show up, whereas in bin\Debug\netcoreapp3.0\ it still opens a blank window as expected. My approach doesn't seem to be working at all, so I think I might be misunderstanding something fundamental about how to get this stuff working.
My goal is to just get the msi to produce a working version of the blank Windows Forms application in C:\Program Files (x86)\MySetup as per the linked tutorial, instead of a faceless dll. Can anybody see where I am going wrong?
To install a working application, you'll need to include all the files written by a publish command.
This tutorial was written for net core 1.1, but looks like it should work.
I have developed a 32-bit C++ application using Visual Studio 2015 (on Windows 10). I want to deploy it onto machines running Windows 7 and later.
I put together a WiX installer and included the VC++ redistributable merge module as described here. The merge module I included was C:\Program Files (x86)\Common Files\Merge Modules\Microsoft_VC140_CRT_x86.msm.
This installer appears to work fine but on Windows 7 the installed program will not run, complaining about missing api-ms-win-crt-runtime-l1-1-0.dll.
From searching I suspect that there may be extra files in the redistributable package vc_redist.x86.exe from here, but the WiX docs tell me to use an msm rather than an exe.
It's also possible that the merge module failed to install. I didn't see any errors but I haven't re-run it with logs enabled to check that possibility.
Another option may be to use burn but I am not familiar with this tool; I will go that route if it's the correct one but I'd prefer to stick with MSI if possible.
The VC++ runtime redistributables got more complicated in Visual Studio 2015. See the VC team blog post about the universal CRT. Basically, the merge module is insufficient:
There will not be a merge module for the Universal CRT. If you currently use the CRT merge modules and still want to deploy the Visual C++ libraries centrally, we recommend that you move to the above mentioned Windows Update package or to the VCRedist. Alternatively, you may choose to link statically to the Universal CRT and the Visual C++ libraries.
We ran into the trouble that the MSI package failed to install the redistributable with MSI Error 1618: 'Another installation is already in progress' during installation/uninstallation. We installed the 2015 redistributable with WIX by using a Bootstraper. For example:
<Chain>
<!-- Microsoft Visual C++ 2015 x86 libraries -->
<ExePackage Cache="no" Compressed="yes" PerMachine="yes" Permanent="yes" Vital="yes"
SourceFile="EXAMPLE_PATH\vc_redist.x86.exe" InstallCommand="/install /passive /norestart">
</ExePackage>
<MsiPackage Id="MainPackage" SourceFile="YOUR_MSI_PACKAGE.msi" DisplayInternalUI="no" Compressed="yes" Vital="yes"/>
</Chain>
It's worth noting that it is now possible to distribute the Universal C Runtime DLLs with your application. The MSDN blog post describes the steps:
Install the Windnows 10 SDK
Go to C:\Program Files (x86)\Windows Kits\10\Redist\ucrt and find the DLLs for the platform you are targeting
Copy them into your application's program directory
They are not big. About 2 megabytes in total.
I ended up using this technique because:
It does not require me to create a separate WiX package and then bootstrap them;
It does not require the user to run any extra installers
I cannot speak to whether it would work on all computers, but it works on the ones I have tested.
I am new to WiX and have built a standalone installer. I would like to detect if the system has .NET 4.5 on it and prompt the user to install this. My development environment is Visual Studio 2010 using the WiX 3.7 toolset.
From some of the tutorials I have seen I should either use WiX 3.6 Burn or use the WiX bootstrapper project template in Visual Studio 2010.
For some reason, when I installed Wix 3.7 I don't have the bootstrapper template (I am not sure if I am missing an extension to download).
Is it better to use the bootstrapper template over Burn? What are the differences?
You need to create a new project named "Bootstrapper Project" (this template must be in your Visual Studio 2010 installation, related to the Windows Installer XML). Here are very good blog posts with manuals:
Introducing Managed Bootstrapper Applications by Heath Stewart
WiX Burn – tips/tricks by Neil Sleightholm
Wix burn, is Wix Bootstrapper. They are the same thing. Burn is simply the name given to the Wix Bootstrapper, but they do tend to switch around between calling it "wix burn" and "wix bootstrapper". But as I've said they are the same thing.
Here is my wix bootstrapper which checks for version of .net then downloads and installs it before installing my .msi You will need to add a reference to WixNetFxExtension.dll
<?xml version="1.0" encoding="UTF-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi" xmlns:bal="http://schemas.microsoft.com/wix/BalExtension" xmlns:util="http://schemas.microsoft.com/wix/UtilExtension">
<Bundle Name="MyProgramInstaller" Version="1.0.0.0" Manufacturer="myCompany" UpgradeCode="yourcodehere">
<!-- here's the license statement, would suggest you update this to something more useful. -->
<BootstrapperApplicationRef Id="WixStandardBootstrapperApplication.RtfLicense" />
<Chain>
<!-- here's the .net download installer you can change this using the following chart -->
<!-- http://wixtoolset.org/documentation/manual/v3/customactions/wixnetfxextension.html -->
<PackageGroupRef Id="NetFx451Web"/>
<MsiPackage Id="myProgram" SourceFile="$(var.SolutionDir)SetupProject1/bin/Release/myProgramInstaller.msi"/>
</Chain>
</Bundle>
</Wix>
I created a WIX project in Visual Studio 2010 over a year ago. It creates an MSI file and a bootstrapper setup.exe. Actually, it creates that pair of files for two languages - English and French. I am just now integrating this project into our TFS CI builds. I'm having trouble getting the CI build to generate the bootstrapper setup.exe files.
We've recently upgraded Wix on all our build servers to Wix 3.6 RC. So, I thought I'd give Burn a try instead of using the old style of bootstrapper. I added a new Bootstrapper project to my solution. The bootstrapper project includes a simple bundle.wxs that just loads the MSI generated by my old MSI project. However, when I try to build I get the following error:
error LGHT0103: The system cannot find the file
'C:\Tf\Advantage\Dev\Solution\Configuration\LaunchPad.Wix\bin\Release\fr-fr\LaunchPad.msi;C:\Tf\Advantage\Dev\Solution\Configuration\LaunchPad.Wix\bin\Release\en-us\LaunchPad.msi'.
My package reference in the bundle looks like this:
<MsiPackage Id="MyApplication" SourceFile="$(var.LaunchPad.Wix.TargetPath)" />
LaunchPad.Wix is the name of the Wix MSI project. If I change the LaunchPad.Wix project to build only one language then it works fine. It looks to me like the bootstrapper project type just doesn't support building setup files for multiple languages. Is this true? Any suggestions for a workaround?
Edit
Upon further investigation, I wonder if bootstrapper projects even support localization. I tried setting my Wix MSI project to create only fr-fr. The setup.exe that my bootstrapper project created with English. When I edit the project properties for the bootstrapper project the "Cultures to build" field is locked down and blank. How would I build a non-english bootstrapper? Is this possible yet?
There are several things going on here:
If you use multiple Cultures, you can't use TargetPath in something outside MSBuild that expects a single filename. As you found, TargetPath is a list of the localized files that were built. However, you can use TargetPath if you qualify the .msi package's output language: <MsiPackage SourceFile="$(var.TestMsi.en-US.TargetPath)" Id="MsiEnUs" />
If you want to create one bootstrapper that can install either/both en-US and fr-FR, you'll need to list each .msi package separately in its own MsiPackage element.
If you want to create two bootstrappers, one en-US and one fr-FR, you'll need to invoke the bootstrapper .wixproj twice, once for each language. Bootstrappers don't support the Cultures "trick" -- it's problematic to produce two outputs from a single invocation of MSBuild (witness the TargetPath problem).
If you're using WixStandardBootstrapperApplication, it automatically tries to localize the UI based on the user UI language, falling back to the system UI language, and finally falling back to English. It looks for localized strings in directories named after the LCID, so you'd have payloads like this:
<Payload Name="1033\thm.wxl" SourceFile="..." />
<Payload Name="1036\thm.wxl" SourceFile="..." />
Unfortunately, WixStandardBootstrapperApplication strings are currently available only for en-US. That's why an fr-FR bootstrapper shows UI in English. You'd need to localize the WiX source file HyperlinkTheme.wxl or RtfTheme.wxl (depending on which theme you use). Both of these files are in src\ext\BalExtension\wixstdba\Resources.
good. it works as Bob Arnson said.
but you must pay attention to the name and the SourceFile of payload.
<BootstrapperApplicationRef Id="WixStandardBootstrapperApplication.RtfLicense">
<Payload Name="2052\thm.wxl" SourceFile="2052\thm.wxl" />
</BootstrapperApplicationRef>
if you change the name to another one. the bootstrapper will not be localized.
I'm trying to fix a bug in VsClojure whereby Visual Studio does not recognize a file with the extension .cljproj as a Clojure project. This only happens when VS is not already open; in other words, if you open VS and then open a solution containing a Clojure project, it recognizes the project. But if you open the solution from Explorer or try to open the project itself from Explorer, it says "This project type is not recognized by Visual Studio."
My hunch is that whatever Visual Studio needs to load in order to recognize this project type is not loaded soon enough when opening the project from Explorer, but is loaded when Visual Studio is already up and running. My question, then, what is it that Visual Studio needs to load in order to recognize an extension's project type? And how do I tell Visual Studio to load it?
I've looked through MSDN's VSIX documentation for answers, but there is a ton of documentation to go through, and in what I looked at, I saw nothing pertaining to this question. I've also looked at IronPython's extension, but it seems to be structured completely differently from VsClojure's. Any help would be much appreciated.
You must add the project type to the registry so Visual Studio can recognize and load the *.cljproj file. See this MSDN article for details along with this article with all the steps involved when adding a new project type.
Unfortunately you can't make this changes from a VSIX, as MSDN states:
The VSIX format uses strictly file-based deployment and does not
support writing to the Global Assembly Cache (GAC), or to the system
registry.
Instead you will need to create an MSI installer. In that case pick your MSI creation method. IronPython uses Windows Installer XML (WiX) toolset so you can use that as your example. Here is a snippet from the WiX XML that sets up some of the registry for the project type:
<Component Id="Comp_PyProgRegistration" DiskId="1" Guid="A7BC75A8-F418-4133-8BF9-490A76E99108">
<RegistryValue Root='HKCR' Key='.pyproj' Type='string' Name='PerceivedType' Value='text' />
<RegistryValue Root='HKCR' Key='VisualStudio.Launcher.pyproj.10.0\DefaultIcon' Type='string' Value='[IpyToolsInstallDir]PythonProject.ico' />
<ProgId Id="VisualStudio.Launcher.pyproj.10.0" Description="IronPython Project">
<Extension Id="pyproj" ContentType="text/plain">
<Verb Id="OpenPyProj" Command="Open" TargetProperty="VSLAUNCHER" Argument=""%1""/>
</Extension>
</ProgId>
</Component>
Check out the Msi directory under in the IronPython source tree for the full example.