Renaming assemblies inside an MSI using Installer Software Development Kit - sql

I've got a legacy project where they had a bunch of visual studio setup projects to create installation packages of the same plugin for different versions of a 3rd party application.
I'm trying to figure out how to build the setup projects so that they work.
Extracting the contents of a previously compiled MSI and the one I get when building the project the assemblies in the Global Assembly Cache folder inside my MSI and the other one are different. The other MSI has a suffix appended to the names of the assemblies.
As a part of the compilation process of the MSIs they apparently had a script renaming assemblies in the compiled MSI packages using the The SQL query strings for Windows Installer.
I have the script and running it against my MSI does not rename the assembly files as looked at when I extract the contents of the MSI.
The SQL statements which I suppose should rename the assemblies are of the following form:
update MsiAssemblyName set Value = 'AssemblyNameSuffix' where Value = 'AssemblyName'
Running the script does change the MSI in some way but I don't see the assembly files renamed.
The question is if it is possible to rename the assembly files in an MSI with SQL this way and if so how can this be achieved?
Thanks!

No, it's not possible. Even if you updated the File table to have the new file name, the assembly would be broken because .NET Assemblies have metadata in them that describe their assembly name, namespace and classes. Renaming a file will break it.

Related

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.

TFS build web application missing BIN for Wix Installer

I added into Solution(contains 30projects) Wix Installer, which is supposed to pack web service folder. Among files i want to pack is BIN file with plenty of dlls. On local with Release mode it works fine, however if i run TFS 2013 build definition over solution i get these:
C:\Builds\1\ABCD_02\WixInstaller\WSwixInstaller\filesToBeInstalled.wxs (97):
The system cannot find the file 'C:\Builds\1\ABCD_02\WixInstaller\WSwixInstaller\..\..\..\ABC WS\bin\ABC.Components.DataAccess.Lib.Utils.dll'.
I asked my colleage who administrate server and he told me that BIN folder isn't created in 'expected' location.
Now i don't have access to server and colleage is unreacheable, is here rule where binaries for all project/within solution are stored?
Update:
Somehow we overlook BIN folder - 'as configured' is and was set in definition however files still couldn't be found - problem was in build order(weirdly in VS2010 was correct) setting dependency wix project on target project helped - problem was that wix project was builded before target one.
Team Build creates uses a MsBuild parameter to redirect the build output of projects. If you need your Wix Installer to package up content that has been redirected, your installer script must be aware of this redirection happening.
The output structure of team build looks like
Build Agent Root
+- Unique build folder
+- src <- This is where your Wix project is placed
+- bin <- This is where Team Build redirects the project outputs to.
+- Test <- This is where Test Results are stored
This allows Team Build to figure out which outputs to copy to the drop location with a lot more accuracy, but it breaks any scripts that have hardcoded (or relative) paths to build outputs.
There is hope though, you can use the $(OutDir) or $(OutputPath) parameter to find the location Team Build has been configured to drop your binaries. You can use the '$(BuildingInsideVisualStudio)'=='' and/or '$(TeamBuildConstants)'=='' to detect whether your Wix Script runs in Visual Studio or in Team Build.
That way you can define multiple source locations for your Wix packages or to set the base directory to a certain value and use that variable in your wix scripts.
Or if you simply want your team build to match your bin structure when running in visual studio, set the 'output location' parameter in your build definition to 'as configured' - see this link for details:
http://blog.stangroome.com/2014/02/10/override-the-tfs-team-build-outdir-property-in-tfs-2013/

Putting new dll in exisiting GAC path using wix

I am working on Wix and I have to place a new dll (Let's say New.dll) as a part of MSI installation into a specific path in GAC where some other dll already resides.(Let's say Exisiting.dll. Please note this dll exists before installing my MSI).
So is there a way I can achieve this? Please note New.dll contains native code and is not .net assembly. Thanks.
The GAC is only for files in strongly-named assemblies. An assembly is a versioned set of files, one of which has a manifest. Creating multi-file assemblies is easy but most tools neither help create nor respect that an assembly may have multiple files. The basic tool is the assembly linker. See How to: Build a Multifile Assembly.
A native DLL can be made part part of an assembly with the /linkresource switch for the C# compiler. If you want to fiddle with a C# project file, you can override the standard Compile target and Csc task with your own that will pass linkresources.
WiX does not handle multi-file assemblies. You have to create File elements for each file in the assembly. All such Files should be in the same Component. This is an instance where having a single component makes sense when Organizing Applications into Components.
If want want a different behavior (that is, replace one of the files), then you have to create a new version of the assembly/Component. Hopefully, that is how the previous native DLL got into the GAC in the first place.
I've only done this a little bit years ago. I'm 99% certain that the new.dll would be a companion file of the old.dll. In other words, the old.msi has a component with old.dll as the keyfile. The new.dll has to be added as an additional file to this component so that MsiPublishAssemblies / Fusion API can publish them together into the same storage directly.
You may be able to do this in a new.msi provided that you sync up the component ID (GUID) and mark it as a shared component. You would have to rebuild old.dll with the same strong name (and AssemblyVersion) but with a higher AssemblyFileVersion / Win32 File Version.
MSI component rules require newer DLL's to be backwards compatible. This goes double for the GAC. This seems to be a substantial change to old.dll. It might make sense to just rev the AssemblyVersion and define this as a whole new component and install side by side in the GAC.
The first thing you are going to want to do is search for the file on the system... You can do this with the FileSearch WiX statement:
<Property Id="PROPFILESEARCHEXISTINGDLL" Secure="yes">
<DirectorySearch Id="EXISTINGDLLFOLDERPATH" Path="[WindowsFolder]\assembly\" Depth="5">
<FileSearch Name="Existing.dll"/>
</DirectorySearch>
</Property>
DirectorySearch Reference: http://wixtoolset.org/documentation/manual/v3/xsd/wix/directorysearch.html
FileSearch Reference: http://wixtoolset.org/documentation/manual/v3/xsd/wix/filesearch.html
This will put the full path to the file in the PROPFILESEARCHEXISTINGDLL property. From here you can then reference this property when placing the file on disk. (Assuming of course your have permissions to write to that location...)

WiX Bundle with dynamic MsiPackage names

I'm converting our current monolithic installer to use a WiX 3.7 Bundle/chain. We have several components that are now building into their own separately-maintainable MSI installers. My next task is to add all of these to a bootloader/bootchainer, but I've hit a snag.
A requirement for our individual installers is that they contain the version in the filename (i.e. MyApplication-5.4.22.msi). I don't see a tool like Heat for collecting MSI packages together, and I don't see a way to add an MsiPackage element with a wildcard to account for varying package names.
As a last resort, I can wrap the bundler inside of another MSBuild script that will 'autocomplete' the filenames and pass the paths in as variables to the bundler. I'm hoping someone can recommend a solution that works directly in the wxs or wixproj setting.
If the msi files are built with WiX Setup projects, the WiX Bootstrapper project can reference them, thereby creating useful WiX variables that are defined as the paths to the msi files.
See my answer here, as well as the list of variables here.
If that's not the case then you can write some MSBuild targets that run before the Build target to figure out the actual file paths. If the available standard and community MSBuild tasks aren't sufficient, you can write your own tasks, either by creating an assembly or using inline code. (And, of course, there is always the Exec task to shell out to a command-line program like cmd.exe, after which you can parse its output to extract the msi paths.)

How can I make sure a downgraded library is installed by my MSI?

I have an MSI that setups my application. It has a single component and installs only to %PROGRAMFILES% (no shared binaries). Simplified, it looks like this
Msi file, Monday build:
Program.exe (v1.0.0)
ThirdPartyLibrary.dll (v2.0.1)
Now, if I discover a bug in the program caused by my upgrade of the ThirdPartyLibrary dll from v2.0.0 to v2.0.1, and thus revert the reference to v2.0.0, it seems my MSI doesn't automatically replace the file in the installation directory?
Msi file, Tuesday build:
Program.exe (v1.0.0)
ThirdPartyLibrary.dll (v2.0) <- downgraded
What is the best practice here to ensure that the program folder always contains exactly the binaries in my setup? Should I a) wipe everything from the setup directory before copying the new files? Is there an option (in Wix) I can use that makes the msi force an overwrite of all files regardless of version?
What if I remove a file from the setup (a file that would cause errors if present at runtime), then the only way to have a working program after the setup, would be if it deleted all files first?
You can use a msi trick. In the File table in the msi database edit the Version column and enter a higher version, 3.0 for example. This way you will take advantage of the file versioning rules.