Bootstrapper: How to compile the application and prerequisite in single .msi package? - visual-studio-2005

I am creating an .msi package for the application which has a prerequisite for installation.
I am using the Visual Studio 2005 Bootstrapper for this task.
To this end, I did the following:
Located the folder C:\Program Files\Microsoft Visual Studio 8\SDK\v2.0\BootStrapper\Packages\ and created a folder for my prerequisite (made it same structure as 'dotnetfx'); created the 'product.xml' and 'package.xml' and placed them appropriately. I kept the xml files very simple so far to test the installation:
product.xml
<?xml version="1.0" encoding="utf-8"?>
<Product ProductCode="MyPrereq" xmlns="http://schemas.microsoft.com/developer/2004/01/bootstrapper">
<PackageFiles CopyAllPackageFiles="false">
<PackageFile Name="MyPrereq.exe" />
</PackageFiles>
<InstallChecks>
</InstallChecks>
<Commands Reboot="None">
<Command PackageFile="MyPrereq.exe" EstimatedInstallSeconds="90">
<InstallConditions>
</InstallConditions>
<ExitCodes>
<ExitCode Value="0" Result="Success"/>
<DefaultExitCode Result="Fail" String="GeneralFailure" FormatMessageFromSystem="true" />
</ExitCodes>
</Command>
</Commands>
</Product>
package.xml
<?xml version="1.0" encoding="utf-8"?>
<Package Name="MyPrereq" Culture="Culture" xmlns="http://schemas.microsoft.com/developer/2004/01/bootstrapper">
<Strings>
<String Name="Culture">en</String>
<String Name="DisplayName">MyPrereq</String>
<String Name="GeneralFailure">A fatal error occurred. The installation failed.</String>
</Strings>
</Package>
Now I can add the prerequisite from the list and build my setup project.
The problem:
The build output is the 'setup.exe', the 'MyApp.msi' package, plus the subfolder called 'MyPrereq' which contains 'MyPrereq.exe'.
I would like the build to create a 'setup.exe' and a single 'MyApp.msi', which would contain the 'MyPrereq' inside, with no additional files/directories.
I know that the .NET framework is another prereq for my app, and it is included in the same .msi, so that should be possible somehow.
How can I achieve this?

You can create a self-extracting installer with tools such as IExpress (coming with Windows) containing all files in a single executable (see this SO posting).
You cannot have an MSI file installing its own pre-requisites. First, because Windows Installer itself is a pre-requisite (and must be installed by a non MSI exe) and second because Windows Installer installations are transactional and don't support the chained execution of MSI files. This basically means that one MSI installation cannot start another MSI installation. As a consequence, any pre-requisites must be installed by a separate bootstrapper (by the way, the installation is no longer transactional - the pre-requisites won't get uninstalled if your MSI installation fails).
There seems to be a basic mis-understanding about the bootstrapper mechanism though. The bootstrapper can currently only be generated by Visual Studio or MSBuild. Afaik it is not possible with WiX. Look for the GenerateBootstrapper task in MSBuild (see this SO posting).

I managed to do that with IExpress.
Had to use a small trick, however, which is described here
Creating a bootstrapper for a VS Shell application
Unfortunately, the MSBuild task
doesn't provide the option to have the
configuration resource use
prerequisite installers found in the
target directory, so you must manually
update the appropriate resource file
to remove the hard-coded path that
looks for prerequisites in a
sub-directory of the same name.
Open the Setup.exe program in Visual
Studio's resource editor
Double-click
the resource named, SETUPCFG in the 41
folder
Search for the "Vs Shell\"
string and delete the two occurrences
that appear
Save the resource file
and the Setup.exe executable will be
updated automatically
Run iexpress
Create a new package by following the
IExpress wizard's steps and make sure
to include the following files: The
MyVSShellApplication.msi file The
Setup.exe bootstrapper file The
vs_shell_isolated.enu.exe file
The problem was that bootstrapper puts the prerequisites into a subfolder, and IExpress does not recognise subfolders. Have to be careful while editing 'setup.exe' too, didn't get it correct on the first try.

Related

How to manage Windows firewall ports while running an MSI installation?

I have MSI Windows Installer files created by using the Wix Toolset and Wix files (*wxs). My requirement is that I need to open or close specific firewall ports while running the MSI installation.
Is there a way that it can be managed through specifications in the Wix files (*wxs) used to make the MSI installer?
There is an extension called FirewallException in WiX. You need to reference it inside your Visual Studio project. Find it at: C:\Program Files (x86)\WiX Toolset v3.11\bin\WixFirewallExtension.dll for a standard installation of WiX.
As to the usage of the actual element:
You can find sample markup on github.com.
Bob Arnson's blog:
http://www.joyofsetup.com/2008/05/17/new-wix-feature-firewall-extension/
Basic usage step-by-step:
In Visual Studio project, add reference to C:\Program Files (x86)\WiX Toolset v3.11\bin\WixFirewallExtension.dll
Right click your WiX project
Click "Add => Reference..." & browse to above path and double click file
Add to top level Wix element in your Project.wxs source file: xmlns:fire="http://schemas.microsoft.com/wix/FirewallExtension"
Then add the markup. Something along these lines:
<Component Feature="ProductFeature">
<File Source="$(env.SystemRoot)\myexecutable.exe">
<fire:FirewallException Id="FWX1" Name="Service" Port="[PORT]" Protocol="tcp" Scope="any" />
</File>
</Component>

Modify exe manifest of InstallShield X (Version 10.5)

I have InstallScript Project created with InstallShield X (Version 10.5)
When I run mt.exe from Windows SDK v7.1A with the following manifest:
MySetup.exe.manifest
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v2">
<security>
<requestedPrivileges>
<requestedExecutionLevel
level='requireAdministrator'
uiAccess='false'
/>
</requestedPrivileges>
</security>
</trustInfo>
</assembly>
using the following command:
# wrong file! MySetup.exe will be truncated!
mt.exe -manifest MySetup.exe.manifest -updateresource:MySetup.exe;#1
the installer (MySetup.exe) is truncated from ~80 MB to ~110 KB. How do I properly embed Admin Privilege Elevation manifest to the installer generated by InstallShield X?
There is a downloadable tool from InstallShield which modifies the manifest of a built setup.exe or update.exe. At this point I don't recall which versions of InstallShield's output it works with. It will remove digital signatures as it modifies the contents of the .exe file.
http://support.installshield.com/kb/view.asp?articleid=Q113245
(As a disclaimer I am paid to work on the product. I still recommend instead using a version of InstallShield which offers the option to select a manifest. I believe that's InstallShield 12 for MSI setup.exe, and something later such as InstallShield 2010 or InstallShield 2011 for InstallScript setup.exe and MSI update.exe files.)
Use the mt.exe tool to update the manifest of the following files (make a backup first!)
C:\Program Files\InstallShield 10.5\Redist\Package Stub\Setup.exe
C:\Program Files\InstallShield 10.5\Redist\Uncompressed Files\Language Independent\Intel 32\setup.exe
C:\Program Files\InstallShield 10.5\Support\Dialog Sampler\Media\Default\Disk Images\Disk1\setup.exe
C:\Program Files\InstallShield 10.5\Support\Dialog Sampler\Media\Skin\Disk Images\Disk1\setup.exe
with the same command as in the question
mt.exe -manifest Setup.exe.manifest -updateresource:Setup.exe;#1
and then rebuild the installer
If this doesn't work, then as pointed out by Michael Urman in his comment, you need to update the manifest for other stubs. The way I look for the stubs is by recursively search the string 6595b64144ccf1df using Notepad++ in InstallShield installation folder. This value is the publicKeyToken that I find in the manifest of my final installer.
You can use any resource editor like XNResourceEditor or mt.exe to extract the manifest and search for files that contain similar manifest under InstallShield installation folder.

TransformXml task could not be loaded from Microsoft.Web.Publishing.Tasks.dll

Has anyone seen this error and know how to fix it?
The "TransformXml" task could not be loaded from the assembly C:\Program Files (x86)\MSBuild\Microsoft\VisualStudio\v11.0\Web\Microsoft.Web.Publishing.Tasks.dll.
Could not load file or assembly 'file:///C:\Program Files (x86)\MSBuild\Microsoft\VisualStudio\v11.0\Web\Microsoft.Web.Publishing.Tasks.dll' or one of its dependencies. The system cannot find the file specified.
Confirm that the declaration is correct, that the assembly and all its dependencies are available, and that the task contains a public class that implements Microsoft.Build.Framework.ITask.
I read elsewhere that the problem is when you don't have SQL Server installed. But I do have SQL Express 2012 x64 installed with SP1. I am also running VS 2013 Professional.
I have ran this exact same solution in VS 2012 express with no problems.
The answers provided by Dai Bok and emalamisura work fine as long as you use Visual Studio 2012.
For VS 2013 this fails as well. In order to make this work with all versions of Visual Studio you should:
Open the project file (.csproj) of the project failing to load
Search for <Import Project="$(MSBuildExtensionsPath)\Microsoft\VisualStudio\v10.0\Web\Microsoft.Web.Publishing.targets" />
Change it to <Import Project="$(MSBuildExtensionsPath)\Microsoft\VisualStudio\v$(VisualStudioVersion)\Web\Microsoft.Web.Publishing.targets" />
Reload the project
That will set the correct version of Visual Studio dynamically and properly.
To get mine to work, I just copied my v10.0 folder and renamed it to v11.0, and things seems to work well from then on. That's the quick fix for now.
As this is probably not the best solution, and although it works, I was going to try installing the Microsoft Windows SDK for Windows 7 and .NET Framework 4 Windows SDK for Windows 7 and .NET Framework 4, but it is taking to long to download.
To fix the issue,
Find the Visual studio Installer in your computer
Click or tap to start the installer, and then select Modify.
From the Individual Components screen, select Asp.net and web development tools and then select Modify/Install.
This solved the issue as it creates the dll's in the mentioned path.
I've been combating this problem on our build server for several days, so I figured I'd document the resolution I came to. First, my build server has the web publishing extensions installed. I can use the TransformXml task to my heart's content inside of a web application project.
To use it outside of a web application project, I tried to add the UsingTask element to my project and point it to the right place using ms build properties (as Benjamin demonstrated). However, they weren't there on my build server (those with easy access to the file system of their build server can probably skip this and just install the relevant package to Visual Studio). I even went so far as to hard code visual studio versions, but it always dropped that error on me.
I finally gave up, pulled the DLLs from my local PC:
C:\Program Files (x86)\MSBuild\Microsoft\VisualStudio\v12.0\Web\Microsoft.Web.Publishing.Tasks.dll
C:\Program Files (x86)\MSBuild\Microsoft\VisualStudio\v12.0\Web\Microsoft.Web.XmlTransform.dll
I uploaded them to source control and added that folder to my build's workspace (Edit Build Definition -> Source Settings -> Source Control Folder). From there, I don't even need to reference the folder -- here's what my UsingTask looks like:
<UsingTask TaskName="TransformXml" AssemblyFile="Microsoft.Web.Publishing.Tasks.dll" />
Now I can use the TransformXml task to my heart's content from any project.
For VS2019
<UsingTask TaskName="TransformXml" AssemblyFile="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(MSBuildToolsVersion
I replaced MSBuildToolsVersion with VisualStudioVersion.
Because there are only v12.0, v14.0 and v15.0 in my VisualStudio folder, I edit my project file and change the reference path from v10.0 to v14.0. Then the project builds successfully.
Before:
<UsingTask TaskName="TransformXml" AssemblyFile="$(MSBuildExtensionsPath)\Microsoft\VisualStudio\v10.0\Web\Microsoft.Web.Publishing.Tasks.dll" />
After:
<UsingTask TaskName="TransformXml" AssemblyFile="$(MSBuildExtensionsPath)\Microsoft\VisualStudio\v14.0\Web\Microsoft.Web.Publishing.Tasks.dll" />
Solutions provided seem to work for using VS as an IDE, but if you use DotnetCore via CLI or on a unix based system this does not work.
I found that the following seem to work
<PropertyGroup>
<XmlTransformDllPath Condition="'$(XmlTransformDllPath)' == '' AND '$(MSBuildRuntimeType)' == 'core'">$(MSBuildSDKsPath)/Microsoft.NET.Sdk.Publish/tools/net5.0/Microsoft.NET.Sdk.Publish.Tasks.dll</XmlTransformDllPath>
<XmlTransformDllPath Condition="'$(XmlTransformDllPath)' == '' AND '$(MSBuildRuntimeType)' != 'core'">$(MSBuildSDKsPath)/Microsoft.NET.Sdk.Publish/tools/net472/Microsoft.NET.Sdk.Publish.Tasks.dll</XmlTransformDllPath>
<XmlTransformDllPath Condition="!Exists($(XmlTransformDllPath))">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\Web\Microsoft.Web.Publishing.Tasks.dll</XmlTransformDllPath>
</PropertyGroup>
<UsingTask TaskName="TransformXml" AssemblyFile="$(XmlTransformDllPath)" />
This solution takes into account netcore, full .net
For some reason MSBuildSDKsPath and MSBuildExtensionsPath32 are different on windows when using CLI vs VS2019
CLI:
MSBuildSDKsPath = C:\Program Files\dotnet\sdk\5.0.103\Sdks
MSBuildExtensionsPath32 = C:\Program Files\dotnet\sdk\5.0.103
Vs2019
MSBuildSDKsPath = C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\MSBuild\Sdks
MSBuildExtensionsPath32 = C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\MSBuild
Which on my Mac returns /usr/local/share/dotnet/sdk/5.0.201
Only problem I see is with the tools/net5.0 part of the name which changes ever release
Also created https://github.com/dotnet/sdk/issues/16469 and answers this on The "TransformXml" task was not found (error MSB4036) on TeamCity build
The correct answer to this is to unload the project in question and then edit the csproj file, look for an entry where they are referencing the 10.0 path and change it to point to 11.0 instead.
You need two things to make it work:
1) Install Visual Studio Build Tools (You don't need the whole Visual Studio, only the VS Build Tools) with selected "Web development build tools" option on your build server
https://www.visualstudio.com/pl/thank-you-downloading-visual-studio/?sku=BuildTools&rel=15
2) Ensure that path to Microsoft.Web.Publishing.Tasks.dll is correct
<UsingTask TaskName="TransformXml" AssemblyFile="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(MSBuildToolsVersion)\Web\Microsoft.Web.Publishing.Tasks.dll" />
For me it started working just by adding reference to the NuGet package MSBuild.Microsoft.VisualStudio.Web.targets v14.0.0.3
Even no need to add UsingTask element to the project file as it mentioned by the package author
https://github.com/pdonald/nuget-webtargets
Just install the NuGet package. The package automatically sets the
$(VSToolsPath) property to use the targets file in the tools folder.
And then I was able to use TransformXml and other tasks, defined in the package, for instance to transform app.config
<Target Name="app_config_AfterCompile" AfterTargets="AfterCompile" Condition="Exists('app.$(Configuration).config')">
<!--Generate transformed app config in the intermediate directory-->
<TransformXml Source="app.config" Destination="$(IntermediateOutputPath)$(TargetFileName).config" Transform="app.$(Configuration).config" />
<!--Force build process to use the transformed configuration file from now on.-->
<ItemGroup>
<AppConfigWithTargetPath Remove="App.config" />
<AppConfigWithTargetPath Include="$(IntermediateOutputPath)$(TargetFileName).config">
<TargetPath>$(TargetFileName).config</TargetPath>
</AppConfigWithTargetPath>
</ItemGroup>
</Target>
Just in case someone is using an SDK-style csproj, you can achieve this without having to install Visual Studio on the build server.
First you should install the SlowCheetah nuget package to your project. Once you install it, you'll see the following in your SDK-style project.
<PackageReference Include="Microsoft.VisualStudio.SlowCheetah" Version="3.2.20">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
</PackageReference>
Then make sure you add the GeneratePathProperty="true" attribute (see below). This is very important for the next part because it'll help you grab the path of where the nuget package is restored on your machine. George Dangl explains it in his article here.
<PackageReference Include="Microsoft.VisualStudio.SlowCheetah" Version="3.2.20" GeneratePathProperty="true">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
</PackageReference>
Import the SlowCheetah targets into your project:
<Import Project="$(PkgMicrosoft_VisualStudio_SlowCheetah)\build\Microsoft.VisualStudio.SlowCheetah.targets" />
You can now use an target command (in this case after publish) to apply some custom transformations. If you need to, you can always hard-code the file names below instead of using the variables in the below example.
<Target Name="AfterPublishs" AfterTargets="Publish">
<TransformTask Source="Web.config" Transform="Web.$(Configuration).MyCustomTransformFile.config" Destination="$(PublishDir)\Web.config" />
</Target>
If you haven't used SlowCheetah before, I recommend checking it out. They have a Visual Studio extension that will make it easier for you to preview transform files.

How to create NuGet package that includes XML intellisense data

This link How do I create an XML Intellisense file for my DLL? explains how to build your dlls so that an XML file is included containing all your documentation headers so that they are available in those IntelliSense popups.
In my company we frequently distribute our own dlls using an internal NuGet package source. When I create NuGet packages for the package source, how do I ensure that someone else gets the dll from the package source, IntelliSense displays the documentation headers for them?
If you distribute your XML files with your NuGet package in the same folder as your Dlls then Visual Studio will then find these XML files and show IntelliSense for your assemblies.
To distribute the IntelliSense XML files you will need to add them to your .nuspec file, for example:
<files>
<file src="bin\IronPython.dll" target="lib\Net40" />
<file src="bin\IronPython.xml" target="lib\Net40" />
</files>
tl;dr documentation files need to be .xml not .XML
I was able to get the XML files included by first enabling the production using the Build tab, checking XML Documentation File in the Output section. Note: for some reason I had to manually change the extension from .XML to lowercase .xml. YMMV. This is the same as the question you referenced, How do I create an XML Intellisense file for my DLL?.
Once done, I created the Nuspec file in the project directory. Here's a sample, you can also generate it with nuget spec MyAssembly.dll - but make sure to edit it and set the values appropriately.
<?xml version="1.0"?>
<package >
<metadata>
<id>$id$</id>
<version>1.0.0</version>
<title>Title for your package</title>
<authors>Package Author</authors>
<owners>Package Owner</owners>
<requireLicenseAcceptance>false</requireLicenseAcceptance>
<description>A description of your library</description>
<releaseNotes>Release notes for this version.</releaseNotes>
<copyright>Copyright 2013</copyright>
<tags>tag1 tag2</tags>
</metadata>
</package>
Once that was done, I used Nuget to package. Note I had to specify the platform because I'm using a 64-bit OS, but I don't have any targets in the project for x64, only AnyCPU
nuget pack MyAssembly.csproj -Prop Configuration=Release;Platform=AnyCPU -build
The assembly and it's associated documentation were automatically included in the package. In addition any packages that you've used in your project are added to the dependency list.
See http://docs.nuget.org/docs/creating-packages/creating-and-publishing-a-package for more information.

How to call a MSI file from another MSI?

I am using WIX for my application's setup project, I have to install device drivers along with my application setup. so I have two driver installer files for each x86 and x64 platforms (since I have to use difxapp_x64/difxapp_86 reference file I need to have two separate installation projects), and one application setup project. now based on the platform I want to call either one of the driver installer msi file and the application installer file from one Msi file ( Bootstrapper !?). How can I accomplish this ?
after a bit of search i come to know in wix 3.6 there is a new tool know as 'Burn', this will help me to call collection of installation packages that are chained together.. so I have created a new setup project as Bootstrapper. but when I build its creating the msi file successfully but could not able to run it.. here is the code:
<?xml version="1.0" encoding="UTF-8"?>
<?define version="1.3.0.3"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
<Bundle Name="Bootstrap" Version="1.0.0.0" Manufacturer="Bootstrap" UpgradeCode="58A81C66-C066-4CA1-9712-D884C11C88BD">
<BootstrapperApplicationRef Id="WixStandardBootstrapperApplication.RtfLicense" />
<Chain>
<ExePackage Id="ExeProject"
SourceFile="../../../CCSetupProject/bin/Release/CCSetupProject.exe"
InstallCommand="/q /ACTION=Install"
Name="iCConnectInstaller"
Vital="yes"
PerMachine="yes"/>
</Chain>
</Bundle>
</Wix>
when I click the Bootstrapper.msi file it says "Preparing to install" and then "This installation package could not be opened. Contact the application vendor to verify that this is a valid Windows Installer package."
dont know what I am missing here!, anybody got this error before ?
You can't by having two separate packages.
To solve the problem you have to build a merge module for the drivers, and then merge it with the main installation.
By having a separate merge module, you can create an additional package which install only the drivers, or you can use product features to select what is gettin installed.

Resources