Install vsix package both on Visual Studio 2015 and Visual Studio 2017 with WIX - wix

I have a WiX setup project that installs VSIX packages using the wix:VsixPackage element from the Vs extension.
I am trying to modify this setup project to support both Visual Studio 2015 and Visual Studio 2017. So I've modified the setup definition like this:
<Component Id="Modeling.Factory" Guid="1A5C7D5C-676E-46D9-9808-5FE79A51B8B3">
<File
Id="Modeling.Factory.vsix"
Name="Primavera.Modeling.Factory.Shell3.vsix"
Source="$(var.SolutionDir)\Bin\Primavera.Modeling.Factory.Shell3.vsix"
Vital="yes">
<wix:VsixPackage
PackageId="FA9F2DC1-30A2-4C88-AFC6-3CD5A49C39CB"
Target="Pro"
TargetVersion="14.0"
Permanent="no"
Vital="yes" />
<wix:VsixPackage
PackageId="FA9F2DC1-30A2-4C88-AFC6-3CD5A49C39CB"
Target="Pro"
TargetVersion="15.0"
Permanent="no"
Vital="yes" />
</File>
</Component>
Notice the two Target and TargetVersion settings.
The setup builds without any warning, both in VS2015 and VS2017.
When I run the setup it fails. The setup log file includes this line that identifies the problem:
MSI (s) (A0:3C) [11:36:57:314]: Executing op: CustomActionSchedule(Action=vim2916624A52A9C02C06B731DECBEAB911,ActionType=3122,Source=C:\Program Files (x86)\Microsoft Visual Studio 14.0\Common7\IDE\VSIXInstaller.exe,Target=/q /skuName:Pro /skuVersion:15.0 "C:\Program Files (x86)\PRIMAVERA\Elevation SDK v3.00\Temp\Primavera.Modeling.Factory.Shell3.vsix" /admin,)
CustomAction vim2916624A52A9C02C06B731DECBEAB911 returned actual error code 2003 (note this may not be 100% accurate if translation happened inside sandbox)
So the problem is that the setup is trying to install the VSIX package to VS2017 using the VS2015 version of the VSIXnstaller.
What am I doing wrong? Is it possibly a bug in WiX?
I am using WiX v3.11.0.1507.
Thanks for any help.

The changes in VS2017 require changes in VsixInstaller that are apparently not feasible without further changes in VS2017: http://wixtoolset.org/development/wips/5433-add-support-to-detect-and-install-vsix-packages-into-vs15/

Related

How to uninstall inno setup application from Wix bundle

My Wix bundle is installing a few 3rd party EXE packages that are packaged with Inno setup. As you know, Inno Setup uninstaller is a separate executable. Basically, when you install AThirdParty.EXE - it creates an unin000.exe within its deployed folder ( e.g. C:\Program Files (x86)\AThirdPartyApp\unins000.exe ), and that's what I need to execute during my bundle uninstall.. Anyone know how to it with Wix Bootstrapper?
Below is an example of my ExePackage:
<PackageGroup Id="MyThirdPartyPackages">
<ExePackage Id="AThirdPartyExe"
DisplayName="A Third Party Exe"
Cache="yes"
Compressed="yes"
PerMachine="yes"
Permanent="no"
Protocol="none"
Vital="yes"
SourceFile=".\AThirdPartyExe.exe"
DetectCondition="AThirdPartyExeExists"
InstallCommand="/VERYSILENT /SUPPRESSMSGBOXES"
UninstallCommand="[ThirtdPartyEXEPath]\unins000.exe" <!-- Can I use uninstallcommand for this?? -->
/>
</PackageGroup>
Assuming Inno Setup doesn't support an /uninstall flag (no idea but if so yet another reason to only use MSI ) and you don't want to repackage the installer into an MSI the quickest solution I can think of is a man in the middle EXE.
InstallShield used to (may still) have a Helper.exe for some of it's setup prerequisites. You would code it to accept a /INSTALL and /UNINSTALL argument and have WiX call that instead. It would in turn call the actual install and uninstall as you described above.

Wix per user installer to detect the Visual C++ 2015 Redistributable

I am creating an .msi installer which has to determine whether the Visual C++ 2015 Redistributable is present in the system and if not then interrupt the installation with custom message. The official Wix documentation refers to the actual installation of the VC++ which I do not wish to do as my installer is "per user" , There are couple of others stackoverflow questions which refer to the bundle rather than the .msi http://wixtoolset.org/documentation/manual/v3/howtos/redistributables_and_install_checks/install_vcredist.html.
Wix Burn vcredist, WIX check if VS2015 C++ redistributable is installed , https://gist.github.com/nathancorvussolis/6852ba282647aeb0c5c00e742e28eb48
So I guess the question is, how to efficiently detect the presense of Visual C++ 2015 Redistributable in the per user installer.
The latest supported Visual C++ downloads
Runtime Detection Approaches
I can find a few ways to detect the presence of the Visual C++ Runtime.
Registry
Keys used by the VCRedist installer (see section below)
Keys mentioned in my original answer - grabbed from this old answer
File Presence & Version Check
Check for presence of core runtime files
See separate section below
MSI API
You can detect whether a specific MSI is installed by looking up the product GUID
Reliable, but hard to keep track of all product GUIDs (different versions)
UPDATE: You can also use the upgrade code as described below. It should remain stable across releases and updates (for each major version and potentially between major versions as well).
Fall-Over EXE?
Suggestions are seen to use an EXE depending on the runtime
Launching it and failing means the runtime is not there or broken
Good & Bad - Evaluation: Option 1 seems to be vulnerable since the merge module variant of deploying the runtime might not write these keys. Option 3 might work well, but it is hard to keep track of all GUIDs. Option 4 seems to already have failed based on the newer runtimes removing certain registry keys. Though fixed now, this could resurface.
File Version Presence / Version Check
The more I look at this, the more I start to think that you have to check for the actual files themselves, and potentially for the right file version. The file vcruntime140.dll in the System32 folder (64-bit version) and SysWOW64 folder (32-bit version)? See files list towards bottom here.
Just adding a link for safe-keeping.
How to detect the presence of the Visual C++ 2012 redistributable package?
Redistributing Visual C++ Files
A test VBScript - for test purposes only (scripts are sometimes blocked by anti-virus):
Set fso = CreateObject("Scripting.FileSystemObject")
MsgBox fso.GetFileVersion("C:\Windows\System32\vcruntime140.dll")
You can detect file presence and version using AppSearch in an MSI file.
Below are some other stuff I wrote up, just leaving it in.
VCRedist
It seems the Visual C++ Redistributable Packages (VCRedist_x86.exe, VCRedist_x64.exe) - which is the recommende way to deploy the runtime - checks the following registry key to determine what versions of the runtime is actually installed:
HKLM\SOFTWARE\Microsoft\VisualStudio\<version>\VC\Runtimes\
The sub-keys x86 and x64 seem to all contain an "Installed" value that is set to 1 when the runtime is installed. I would assume - without having had time to test it all - that you then can check:
HKLM\SOFTWARE\WOW6432Node\Microsoft\VisualStudio\14.0\VC\Runtimes\x64 Installed = 1
HKLM\SOFTWARE\WOW6432Node\Microsoft\VisualStudio\14.0\VC\Runtimes\x86 Installed = 1
Merge Module: After a brief check, it looks like these values are not written by the merge modules that can also be used to distribute this runtime. I do not have the time or means to check this properly now.
Astonishingly both version 2015 and version 2017 of the runtime write to the 14.0 key - since they are binary compatible. If the 2017 version is installed, then the VCRedist executable will return an error since no install is needed. Weird indeed. But for your purpose that should be besides the point. Source.
MSI API - Retrieve Product Codes
Mailbag: How to detect the presence of the VC 8.0 runtime redistributable package
Updated VC 8.0 runtime redistributable packages are included in Visual Studio 2005 SP1
How can I find the product GUID of an installed MSI setup?
UPDATE: installer.ProductState - normal installed state is 5:
I forgot about the ProductState property when writing the below.
You can check for an installed product with two lines of code if you
have the actual product code:
Dim installer : Set installer = CreateObject("WindowsInstaller.Installer")
MsgBox installer.ProductState("{00000000-0000-0000-0000-000000000001}")
Here is even one more way to do it: MSDN: How to programmatically check for the presence of a Windows Installer-based product by using its product code.
Tip: I wouldn't use this approach seeing as the product code changes frequently when products are updated. Hence I like better to
check for file versions of core-runtime files. This seems more
reliable for the future (provided version parsing is done correctly
and reliably - don't roll your own).
Mockup:
Public installer
Set installer = CreateObject("WindowsInstaller.Installer")
' Don't have the 2015 GUID
VC2015 = CheckForProductCode("{00000000-0000-0000-0000-000000000000}")
VC2017 = CheckForProductCode("{C77195A4-CEB8-38EE-BDD6-C46CB459EF6E}")
MsgBox "VC2015: " & CStr(VC2015) & vbCrLf & "VC2017: " & CStr(VC2017)
Function CheckForProductCode(productcode)
CheckForProductCode = False
For Each product In installer.ProductsEx("", "", 7)
If(LCase(productcode) = LCase(product.ProductCode)) Then
CheckForProductCode = True
Exit For
End If
Next
End Function
Update based on Zett42's suggestion to enumerate products sharing the same upgrade code:
Set installer = CreateObject("WindowsInstaller.Installer")
' Enumerate all products related to "Microsoft Visual C++ 2008 Redistributable - x86 9.0.30729.4148"
' {AA783A14-A7A3-3D33-95F0-9A351D530011} is the upgrade code
Set upgrades = installer.RelatedProducts("{AA783A14-A7A3-3D33-95F0-9A351D530011}")
For Each u In upgrades
MsgBox u, vbOKOnly, "Product Code: "
Next
Deploying The Visual Studio C++ Runtime
Beyond detection, there are several approaches for distributing the Visual Studio C++ Runtime:
Static Linking
Visual C++ Redistributable Packages
VCRedist_x86.exe, VCRedist_x64.exe, or VCRedist_arm.exe
Program Files(x86)\Microsoft Visual Studio\2017\edition\VC\Redist\MSVC\lib-version
Redistributable Merge Modules (.msm files)
Insufficient for some purposes (The universal CRT):
Redistributables for deploying C++ exe developed with Visual Studio 2015 on Windows 7
WIX merge c++ runtime
Local Application Folder
Copy DLLs to the local application folder
Not recommended for servicing reasons (updates, security fixes)
Links For Safe Keeping:
Redistributables for deploying C++ exe developed with Visual Studio 2015 on Windows 7
How to detect whether I need to install VCRedist?
WIX merge c++ runtime
How to detect if Visual C++ 2017 Redistributable is installed
Old Answer
There is this old post. I am not too fond of direct registry reads, let me see if I can find a more reliable way, but maybe have a look in the mean time: Detect if Visual C++ Redistributable for Visual Studio 2012 is installed
Just one more link, how to find the Windows Installer product code of products that are installed: How can I find the product GUID of an installed MSI setup?
You can use LaunchConditions from WiX Toolset. The detection can be done by RegistrySearch.
Until version 2015 it was just a registry key, GUID value. Since 2017 and still in 2019 the key is concat (merged), so it is not that easy anymore. This is way I used a loop from 21 to 40 to find all places. C++ Runtime Documentation.
Add the following lines to your product.wxs inside the Product elemnent:
...
<!-- Visual C++ Redistributable 2015, 2017 and 2019 (x86) -->
<Property Id="CPPRUNTIME2015X86" Secure="yes">
<!-- C++ 2015 -->
<RegistrySearch Id="mfc140x86_23026" Root="HKLM" Key="SOFTWARE\Classes\Installer\Dependencies\{74d0e5db-b326-4dae-a6b2-445b9de1836e}" Type="raw" />
<RegistrySearch Id="mfc140x86_24215" Root="HKLM" Key="SOFTWARE\Classes\Installer\Dependencies\{e2803110-78b3-4664-a479-3611a381656a}" Type="raw" />
<!-- C++ 2017 -->
<RegistrySearch Id="mfc1416x86" Root="HKCR" Key="Installer\Dependencies\VC,redist.x86,x86,14.16,bundle" Type="raw" />
<!-- C++ 2019 -->
<?foreach CPPRUNTIMEVERSIONPREFIX in 21;22;23;24;25;26;27;28;29;30;31;32;33;34;35;36;37;38;39;40?>
<RegistrySearch Id="mfc14$(var.CPPRUNTIMEVERSIONPREFIX)x86" Root="HKCR" Key="Installer\Dependencies\VC,redist.x86,x86,14.$(var.CPPRUNTIMEVERSIONPREFIX),bundle" Type="raw" />
<?endforeach ?>
</Property>
<Condition Message="Microsoft Visual C++ 2015-2019 (x86) Redistributable missing">
<![CDATA[((REMOVE="ALL")) OR Installed]]>
</Condition>
<!-- Visual C++ Redistributable 2015, 2017 and 2019 (x64) -->
<?if $(var.Platform) = x64 ?>
<Property Id="CPPRUNTIME2015X64" Secure="yes">
<!-- C++ 2015 -->
<RegistrySearch Id="mfc140x64_23026" Root="HKLM" Key="SOFTWARE\Classes\Installer\Dependencies\{e46eca4f-393b-40df-9f49-076faf788d83}" Type="raw" />
<RegistrySearch Id="mfc140x64_24215" Root="HKLM" Key="SOFTWARE\Classes\Installer\Dependencies\{d992c12e-cab2-426f-bde3-fb8c53950b0d}" Type="raw" />
<!-- C++ 2017 -->
<RegistrySearch Id="mfc1416x64" Root="HKCR" Key="Installer\Dependencies\VC,redist.x64,amd64,14.16,bundle" Type="raw" />
<!-- C++ 2019 -->
<?foreach CPPRUNTIMEVERSIONPREFIX in 21;22;23;24;25;26;27;28;29;30;31;32;33;34;35;36;37;38;39;40?>
<RegistrySearch Id="mfc14$(var.CPPRUNTIMEVERSIONPREFIX)x64" Root="HKCR" Key="Installer\Dependencies\VC,redist.x64,amd64,14.$(var.CPPRUNTIMEVERSIONPREFIX),bundle" Type="raw" />
<?endforeach ?>
</Property>
<Condition Message="Microsoft Visual C++ 2015-2019 (x64) Redistributable missing">
<![CDATA[((REMOVE="ALL")) OR Installed]]>
</Condition>
<?endif ?>
...

WIX merge c++ runtime

I have merged msm for vs 2015 crt:
<DirectoryRef Id="TARGETDIR" >
<Merge Id = "Microsoft_VC140_CRT_x64.msm" FileCompression = "yes" Language = "1033" SourceFile = "..\\..\\..\\..\\..\\..\\..\\external\\tools\\systemsetups\\merge_modules\\Microsoft_VC140_CRT_x64.msm" DiskId = "1" />"
</DirectoryRef>
<Feature>
<Feature Id="Complete" Title="Complete" Absent="allow" Level="1">
...
<MergeRef Id="Microsoft_VC140_CRT_x64.msm"/>
...
</Feature>
but I still receiving:
---------------------------
MyApp.exe - System Error
---------------------------
The program can't start because mfc140u.dll is missing from your computer. Try reinstalling the program to fix this problem.
---------------------------
OK
---------------------------
Any ideas how to merge it properly?
It seems Microsoft recommends you use one of the redist executables (vcredist_x86.exe, vcredist_x64.exe) instead of the merge modules (see towards bottom) these days since the 2015 versions of the runtimes are more complicated than before and the merge modules are basically insufficient: "There will not be a merge module for the Universal CRT".
UPDATE: How to install the exe binary VCRedist along with your MSI?.
This is fully explained by Bob Arnson in this answer: Redistributables for deploying C++ exe developed with Visual Studio 2015 on Windows 7 (must read link - it is the answer, I just added this one to throw in some further links as well).
Also, I don't have the list of merge modules in front of me on this Linux box, but perhaps there is an x86 version that you need - you are installing the x64 version? Just checking - these bitness issues are driving us all crazy.
Some Links:
Redistributing Visual C++ Files
Walkthrough: Deploying a Visual C++ Application By Using the Visual C++ Redistributable Package
Redistributing Components By Using Merge Modules

Working sample for installing a VSIX extension for VS2017 using WixToolset?

I'm trying to install a VSIX Extension into Visual Studio 2017 from a Setup created with the WIX Toolset.
I found this page:
http://wixtoolset.org/development/wips/5433-add-support-to-detect-and-install-vsix-packages-into-vs15/
But its not fully clear whether the "proposals" on that page were really implemented. I did a number of experiments, with no success.
Have the features posposed on the above page been implemented in WiX v3.11.1?
There seems to be some support for VS2017 in WIX v3.11.1, but when I use the VSExtension:VsixPackage element in my Product.wxs file, it seems that the latest VSIXInstaller.exe (of my VS2017 community) isn't found and my Setup Fails.
Can someone provide a working example for this?
Thanks!
I can only tell you my strategy for IsWiX:
https://github.com/iswix-llc/iswix
iswix/Source/Application/IsWiXNewAddIn/
iswix/Source/Installer/IsWiXNewAddInMM/
iswix/Source/Installer/IsWiX/Code/Product.wxs
I'm able to install to VS2013-2017 this way.
What is IsWiX?
https://github.com/iswix-llc/iswix-tutorials
PS- 60 min complimentary dev to dev screenshares are available.
Installing extensions in Visual Studio versions newer than 2015 is not supported by WiX, despite it being able to detect VS 2017 and VS 2019 instances … which is kind of odd to be honest.
There is still the option of using the detected installations to launch the installer, though that might break unexpectedly.
You can try this:
Add WiX VSExtension (obviously):
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi" xmlns:VSExtension="http://schemas.microsoft.com/wix/VSExtension">
Define and set a property containing the VSIX Installer location (done here for Visual Studio 2019):
<Property Id="Vs16VsixInstaller" Value="0" />
<SetProperty Action="SetVs16VsixInstaller" Id="Vs16VsixInstaller" Value="[VS2019_IDE_DIR]VSIXInstaller.exe" Sequence="both" After="AppSearch" />
Define a component containing the extension:
<Component Id="MyVSExtension" Directory="VisualStudioExtensionsFolder" Guid="PUT-GUID-HERE">
<RegistryValue KeyPath="yes" Root="HKMU" Key="Software\[Manufacturer]\[ProductName]" Name="MyVSExtensionInstalled" Type="string" Value="" />
<VSExtension:VsixPackage File="MyVSExtension.vsix" PackageId="PUT-PACKAGE-ID-HERE" VsixInstallerPathProperty="Vs16VsixInstaller" />
</Component>
This worked in my case and I don't think there is a much better way of doing this while also keeping the solution simple.

Web Installer XML referring files from TFS

<Component Id="ProductComponent1">
<File Id="Default.aspxName="Default.aspx"Source="..\WebApplication2\Default.aspx" />
</Component>
What modification would help include the same file from TFS rather than my local system.
I am not aware of any mechanism by which a WIX build can pull files directly from Team Foundation Server (TFS). If this is your intention, you could use a tf get command to pull the latest version prior to the WIX build. For more information on tf get see https://msdn.microsoft.com/en-us/library/fx7sdeyf(v=vs.100).aspx.
If the WIX project is part of a Team Build, the answer to this question may be relevant: Set location of binaries in wixproj file.