How can dependencies for a CustomBootstrapperApplication.dll be packaged? - wix

I'm creating a wix burn custom bootstapper application dll.
The installer neeeds to perform some validation before allowing the install to complete. To do this I use a third party dll. When I run the installer exe, I get an error that the dll is missing from my computer. I tried to package it like this:
<BootstrapperApplication SourceFile="$(var.Build.Output)MyCustomBootstrapperApplication.dll">
<Payload Id="ThirdPartyDependencyDll" SourceFile="$(var.Build.Output)ThirdPartyDependency.dll"/>
</BootstrapperApplication>
But, that doesn't seem to work. Is there a way of creating a custom bootstrapper and packaging dependant dlls with it?
Thanks.

The solution I found was to switch the dll to delay link. Then, in BootstapperApplicationCreate, use AddDllDirectory to add the temp path to the process's dll search paths, and then LoadLibraryEx on it with flags specified to get it to search the modified path.

Related

How to extract MSVC rutime libraries from merged `Microsoft_VC141_CRT_x64.msm` during setup verification

Background
I have complex C++ application which is installed using msi installer (defined with wix).
My application need MSVC run time libraries so Microsoft_VC141_CRT_x64.msm is merged to my installer.
<DirectoryRef Id="APPDIR">
<Merge Id="M.visualStudioRuntime" Language="0" SourceFile="$(var.DependenciesPath)/Microsoft_VC141_CRT_x64.msm"
DiskId="1" />
</DirectoryRef>
....
<FeatureRef Id="F.SomeComponent">
....
<MergeRef Id="M.visualStudioRuntime" />
</FeatureRef>
Now during installation process some data on remote server have to be verified. For that task, I'm extracting my application dll to temporary folder, loading library and execute some function with required parameters. Depending on outcome installation setup is allowed to continue or not.
This dll depends on third party (ok not fully third party it comes from other team) C++ library which also uses MSVC run-time so static linking is not acceptable solution.
Problem
When I'm loading my application dll from temporary folder it needs those MSVC run time libraries. To do that I need exact those dlls to this temporary folder.
Problem is observed only on Windows 2012, other supported Windows versions have this run time preinstalled.
Question
What is best way to extract those MSVC runtime libraries to temporary folder?
Notes
I've inherited this installer and current implementation manually embeds those dll (as duplicates) in installer extract them based on predefined id. This is bad solution and I wish need to fix it properly.
C++: Are you running a C++ custom action that needs those runtimes? Try to statically link as explained here - then there is no need for the VCRuntime files. If you are not running C++, please let us know.
Inlined Essence: Project settings => C/C++ => Code Generation => Change the runtime library setting to multithreaded instead of multithreaded dll.
Custom Action Tips: Here is an answer on common C++ custom action problems: Interrupt installation when custom action returns error.
Secondary Answer: To extract files from a merge module, the easier approach is to add it to a project, build an MSI and then run administrative installation on the MSI - which is a glorified file extraction from the MSI: What is the purpose of administrative installation initiated using msiexec /a?
Basic Command:
msiexec.exe /A MySetup.msi

Unable to build WixStdBootstrapperApplication - get error "C:\tools\WixBuild.props" was not found

I am trying to make changes to the WixStandardBootstrapperApplication.cpp and generate a dll as per the suggestion from this link. I have downloaded the wix310-debug source and am modifying the file present under wix310-debug\src\ext\BalExtension\wixstdba\ location. There is a wixstdba.vcxproj file under this location which I am trying to open using Visual Studio 2012. Whenever I try to do that I get the error:
Unable to read the project file "wixstdba.vcxproj". The imported project "C:\tools\WixBuild.props" was not found.
I am not sure what should I do to correct this. Also, based on the referenced link, I think I am updating the correct file but let me know if that is not the case. Any help in this would be great. Thanks in advance.
In your vcxproj there's a line like this:
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildProjectDirectory), wix.proj))\tools\WixBuild.targets" />
The debug source isn't really the source of wix. It includes all the wix source files but it is not really buildable. This zip has all the built pdbs and is used to debug only.
You want to download the wix source from wixtoolset's github so that you can build wixstdba. But, this is for version 3.10.3 currently and may have some version specific changes but I don't see anything that would be an issue using the dll built here against wix 3.10.2 since the engine and bootstrapper application interfaces should have remained the same.
But, you should be able to build all this with only the WixStdBA project. You will have to copy over the wixstdba folder. Edit the vcxproj and remove the import line mentioned above (it should be near the bottom).
Now, add this project to your a new solution or your installer solution in visual studio. We need to add addition include and library directories. All these include directories will be in your wix install location (default C:\Program Files (x86)\WiX Toolset v3.10) In Properties -> C/C++ -> General -> additional include directories add your wix SDK include path. If you are using visual studio 2013 you can use the full path or you can use "$(WIX)\SDK\vs2013\inc". $(WIX) should reference the WIX environment variable which points to the install directory which is added when installing wix. This should be the better option if you will be building on a build system with wix installed since the location may be different across machines.
Now for addition library directories, we go to the Properties -> Linker -> General -> Additional Library Directoryes and add in the correct lib path. If you are using visual studio 2013 you want to put in $(WIX)\SDK\vs2013\lib\x86. Finally we need to reference the libs that are needed to build the bootstrapper dll. Under Linker -> Input -> Additional Dependencies, add in "dutil.lib;balutil.lib". My additional dependencies has a lot more stuff and I don't remember if it was by default there. Here's my Additional Dependencies in full anyways
dutil.lib;balutil.lib;advapi32.lib;comctl32.lib;comdlg32.lib;gdi32.lib;gdiplus.lib;kernel32.lib;msimg32.lib;odbc32.lib;odbccp32.lib;ole32.lib;oleaut32.lib;shell32.lib;shlwapi.lib;user32.lib;uuid.lib;wininet.lib;winspool.lib;version.lib;%(AdditionalDependencies)
With this you should be able to build the wixstdba project and get a dll built. Without editing any code this should be the exact same as the wix included wixstdba.dll.
You could try referencing this dll instead of the wix included one (have to define your own BootstrapperApplication instead of using the BootstrapperApplicationRef to one of the wix ones) or just drop in this dll into your wix location's bin.

WiX installer and redistribution of libstdc++6.dll from MinGW

I am building a MSI installer with WiX for redistributing my MinGW64 application. This requires to ship MinGW dlls with the executable.
The libstdc6.dll file is not versionned. What is the cleanest approach for this?
I have tried:
Adding a companion file to the dll component, pointing to the main app exe, which is versionned. However, wix complains that I cannot set a companion to a dll
Putting the dll in the main app exe component, but this is discouraged in every wix faq, howto and forum...
Adding attribute DefaultVersion="!(bind.FileVersion.mainapp.exe)" to the dll file element for overriding the (missing) dll version. This seems to work at first glance, but wix is issuing warnings related to this:
C:\Users\Etienne\Documents\coding\ocean\ocean.wxs(116) : warning
LGHT1103 : The DefaultVersion '!(bind.FileVersion.mainapp.exe)' was used
for file 'libstdc6.dll' which has no version. No entry for this file
will be placed in the MsiFileHash table. For unversioned files,
specifying a version that is different from the actual file may result
in unexpected versioning behavior during a repair or while patching.
Version the resource to eliminate this warning.
What is the best way to solve this?
Thanks,
Etienne
IMHO, your best bet is option #2. All the rules assume that executable code would be properly versioned and thus are best deployed as KeyPaths of their respective Components. Since the .dll is not versioned, placing it as a data file with a versioned file is the next best thing.
Although, for the record, versioning the .dll is by far the most optimal solution. :)

Wix Bind Substring or Split

I'm trying to get a Wix installer written that does some TypeLib registration.
I'm already pulling the FileVersion off a registered file elsewhere using
!(bind.FileVersion.#InteropDll)
but I want to do the same thing for the TypeLib, which only has separate MajorVersion and MinorVersion attributes. Ideally, I'd like to do
<TypeLib ...
MajorVersion="!(bind.FileVersion.InteropDll).Split('.')[0]"
MinorVersion="!(bind.FileVersion.InteropDll).Split('.')[1]">
How can I accomplish this (or the like)? ...Or should I just not bother with all this and invoke regasm on the dll file at install time?
Thanks.
The WiX toolset doesn't support doing that today. It's an interesting feature request. I would never call regasm during an install. It's way to hard to get rollback and patching and all that working correctly by shelling out to an external executable.

How to access a temporary Exe or DLL from a DLL Custom action (C++ DLL) in MSI/WIX project?

I have two use cases: 1) loading a temporary DLL during a custom action and 2) executing a temporary EXE from a custom action. The custom action DLL is unmanaged C++. I cannot figure out how to get this working correctly. Including the DLL is easy enough but LoadLibrary is failing as it cannot find the DLL. I also cannot seem to get the physical path of the extracted DLL in order to specify full path in LoadLibrary. Any help is appreciated. I'm using WIX btw for this work.
If you have included the dll and the exe in the Binary Table of the msi, the files will be physically present in the %Temp% folder of the currently logged in user which gets mapped to SUPPORTDIR property of Windows Installer.
You need to use MsiGetProperty to get the SUPPORTDIR and use that in the LoadLibrary.
One thing to remember - Windows Installer usually extracts files from Binary table to %TEMP%, however - the current work directory is often set to c:\windows\installer.
My suggestion - extract the temporary .dll from Binary table yourself when you need it. This gives you the control of when it's saved to. Just remember that you need write permission to the location, so usually some subdir of %temp% is the best choice.