Refactor MSI code to make it easier to add a WiX EXE installer (#13139)

This commit is contained in:
Travis Plunk 2020-07-10 10:46:00 -07:00 committed by GitHub
parent 0f6fe9b046
commit 3a2c164ec6
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 1107 additions and 1056 deletions

View file

@ -4,16 +4,17 @@
<!-- The URL for add/remove programs -->
<!-- TBD:Point to the actual release -->
<?define InfoURL="https://github.com/PowerShell/PowerShell" ?>
<?define ProductName = "$(env.ProductName)" ?>
<?define ProductSimpleVersionWithNameAndOptionalArchitecture = "$(var.ProductName) $(env.SimpleProductVersion) ($(sys.BUILDARCH))"?>
<?define ProductSimpleVersionWithNameAndOptionalArchitecture = "$(var.ProductName) $(var.SimpleProductVersion) ($(sys.BUILDARCH))"?>
<?if $(var.IsPreview)=True?>
<?define PwshPath = "[VersionFolder]preview"?>
<?define IconPath = "assets\Powershell_av_colors.ico"?>
<?else?>
<?define PwshPath = "[VersionFolder]"?>
<?define IconPath = "assets\Powershell_black.ico"?>
<?endif?>
<!-- UpgradeCode GUID MUST REMAIN SAME THROUGHOUT ALL VERSIONS, otherwise, updates won't occur. -->
<?if $(sys.BUILDARCH)=x64?>
<?define ExplorerContextMenuDialogText = "&$(var.ProductName) $(env.SimpleProductVersion)"?>
<?define ExplorerContextMenuDialogText = "&$(var.ProductName) $(var.SimpleProductVersion)"?>
<?define UpgradeCodePreview = "39243d76-adaf-42b1-94fb-16ecf83237c8"?>
<?define UpgradeCodeRelease = "31ab5147-9a97-4452-8443-d9709f0516e1"?>
<?if $(var.IsPreview)=True?>
@ -22,7 +23,7 @@
<?define UpgradeCode = $(var.UpgradeCodeRelease)?>
<?endif?>
<?else?>
<?define ExplorerContextMenuDialogText = "&$(var.ProductName) $(env.SimpleProductVersion) ($(sys.BUILDARCH))"?>
<?define ExplorerContextMenuDialogText = "&$(var.ProductName) $(var.SimpleProductVersion) ($(sys.BUILDARCH))"?>
<?define UpgradeCodePreview = "86abcfbd-1ccc-4a88-b8b2-0facfde29094"?>
<?define UpgradeCodeRelease = "1d00683b-0f84-4db8-a64f-2f98ad42fe06"?>
<?if $(var.IsPreview)=True?>
@ -31,15 +32,11 @@
<?define UpgradeCode = $(var.UpgradeCodeRelease)?>
<?endif?>
<?endif?>
<?define ProductVersion = "$(env.ProductVersion)" ?>
<?define SimpleProductVersion = "$(env.SimpleProductVersion)" ?>
<?define ProductSemanticVersion = "$(env.ProductSemanticVersion)" ?>
<?define ProductProgFilesDir = "$(env.ProductProgFilesDir)" ?>
<!-- Explorer context submenu entries. The ampersand denotes the keyboard shortcut. -->
<?define ExplorerContextSubMenuDialogText = "Open &here"?>
<?define ExplorerContextSubMenuElevatedDialogText = "Open here as &Administrator"?>
<!-- ps1 context submenu entries. -->
<?define PowerShellFileContextSubMenuDialogText = "Run with $(var.ProductName) $(env.SimpleProductVersion)"?>
<?define PowerShellFileContextSubMenuDialogText = "Run with $(var.ProductName) $(var.SimpleProductVersion)"?>
<Product
Id="*"
Name="PowerShell $(var.SimpleProductVersion)-$(sys.BUILDARCH)"
@ -50,7 +47,7 @@
<!-- Properties About The Package -->
<Package Id="*" Keywords="Installer" Platform="$(sys.BUILDARCH)" InstallerVersion="200" Compressed="yes" InstallScope="perMachine" Description="PowerShell package" Comments="PowerShell for every system" />
<!-- Add PowerShell icon for executable -->
<Icon Id="PowerShellExe.ico" SourceFile="$(env.IconPath)" />
<Icon Id="PowerShellExe.ico" SourceFile="$(var.IconPath)" />
<!-- Add PowerShell icon in Add/Remove Programs -->
<Property Id="ARPPRODUCTICON" Value="PowerShellExe.ico" />
<!-- Set properties for add/remove programs -->
@ -60,7 +57,7 @@
<WixVariable Id="WixUIDialogBmp" Value="assets\WixUIDialogBmp.png" />
<WixVariable Id="WixUIExclamationIco" Value="assets\WixUIInfoIco.png" />
<WixVariable Id="WixUIInfoIco" Value="assets\ps_black_32x32.ico" />
<Property Id="WIXUI_EXITDIALOGOPTIONALCHECKBOXTEXT" Value="Open $(env.ProductName)" />
<Property Id="WIXUI_EXITDIALOGOPTIONALCHECKBOXTEXT" Value="Open $(var.ProductName)" />
<!-- Default value of Checkbox of starting PowerShell after installation -->
<Property Id="WixShellExecTarget" Value="[VersionFolder]pwsh.exe"/>
<!-- This changes the default setting from "reinstall if the file is a newer version" to "reinstall if the file is a different version" -->
@ -106,7 +103,7 @@
<Control Id="BottomLine" Type="Line" X="0" Y="234" Width="370" Height="0" TabSkip="yes" />
<!-- Button row -->
<!-- Checkbox to allow starting PowerShell after the installation (in UI mode only) -->
<Control Id="LaunchCheckBox" Type="CheckBox" X="10" Y="243" Width="170" Height="17" Property="LAUNCHAPPONEXIT" Hidden="yes" CheckBoxValue="1" Text="Launch $(env.ProductName)" >
<Control Id="LaunchCheckBox" Type="CheckBox" X="10" Y="243" Width="170" Height="17" Property="LAUNCHAPPONEXIT" Hidden="yes" CheckBoxValue="1" Text="Launch $(var.ProductName)" >
<Condition Action="show">NOT Installed</Condition>
</Control>
<Control Id="Back" Type="PushButton" X="180" Y="243" Width="56" Height="17" Disabled="yes" Text="!(loc.WixUIBack)" />
@ -129,7 +126,7 @@
<![CDATA[ Installed OR $(var.MinOSVersionSupported) ]]>
</Condition>
<!-- Information About When Older Versions Are Trying To Be Installed-->
<MajorUpgrade AllowSameVersionUpgrades="yes" DowngradeErrorMessage="A newer version of $(env.ProductName) is already installed." />
<MajorUpgrade AllowSameVersionUpgrades="yes" DowngradeErrorMessage="A newer version of $(var.ProductName) is already installed." />
<!-- Embed Cabinet Files in Product-->
<MediaTemplate EmbedCab="yes" />
<!-- In Your Wix Setup Project, Add A Reference To WixUIExtension.dll -->
@ -159,7 +156,7 @@
</DirectorySearch>
</DirectorySearch>
</Property>
<Condition Message="$(env.ProductName) requires the Universal C Runtime to be installed to enable remoting over WinRM. You can find a download link to it here: https://aka.ms/pscore6-prereq">
<Condition Message="$(var.ProductName) requires the Universal C Runtime to be installed to enable remoting over WinRM. You can find a download link to it here: https://aka.ms/pscore6-prereq">
<![CDATA[Installed OR UNIVERSAL_C_RUNTIME_INSTALLED]]>
</Condition>
<!-- Prerequisite check for Windows Management Framework -->
@ -168,7 +165,7 @@
<FileSearch Id="pwrshplugin" Name="pwrshplugin.dll" MinVersion="6.3.9600.16383"/>
</DirectorySearchRef>
</Property>
<Condition Message="$(env.ProductName) requires the Windows Management Framework 4.0 or newer to be installed to enable remoting over WinRM. You can find download links here: https://aka.ms/pscore6-prereq">
<Condition Message="$(var.ProductName) requires the Windows Management Framework 4.0 or newer to be installed to enable remoting over WinRM. You can find download links here: https://aka.ms/pscore6-prereq">
<![CDATA[Installed OR PWRSHPLUGIN_VERSION ]]>
</Condition>
<Directory Id="TARGETDIR" Name="SourceDir">

File diff suppressed because it is too large Load diff

View file

@ -468,7 +468,7 @@ function Invoke-CIFinish
$artifacts = New-Object System.Collections.ArrayList
foreach ($package in $packages) {
if (Test-Path $package)
if (Test-Path $package -ErrorAction Ignore)
{
Write-Log "Package found: $package"
}

View file

@ -2996,21 +2996,6 @@ function New-MSIPackage
Write-Verbose "Create MSI for Product $productSemanticVersionWithName"
[Environment]::SetEnvironmentVariable("ProductSourcePath", $staging, "Process")
# These variables are used by Product.wxs in assets directory
[Environment]::SetEnvironmentVariable("ProductName", $ProductName, "Process")
[Environment]::SetEnvironmentVariable("ProductVersion", $ProductVersion, "Process")
[Environment]::SetEnvironmentVariable("SimpleProductVersion", $simpleProductVersion, "Process")
[Environment]::SetEnvironmentVariable("ProductSemanticVersion", $ProductSemanticVersion, "Process")
[Environment]::SetEnvironmentVariable("ProductVersionWithName", $productVersionWithName, "Process")
if (!$isPreview)
{
[Environment]::SetEnvironmentVariable("IconPath", 'assets\Powershell_black.ico', "Process")
}
else
{
[Environment]::SetEnvironmentVariable("IconPath", 'assets\Powershell_av_colors.ico', "Process")
}
$fileArchitecture = 'amd64'
$ProductProgFilesDir = "ProgramFiles64Folder"
if ($ProductTargetArchitecture -eq "x86")
@ -3018,17 +3003,11 @@ function New-MSIPackage
$fileArchitecture = 'x86'
$ProductProgFilesDir = "ProgramFilesFolder"
}
[Environment]::SetEnvironmentVariable("ProductProgFilesDir", $ProductProgFilesDir, "Process")
[Environment]::SetEnvironmentVariable("FileArchitecture", $fileArchitecture, "Process")
$wixFragmentPath = Join-Path $env:Temp "Fragment.wxs"
$wixObjProductPath = Join-Path $env:Temp "Product.wixobj"
$wixObjFragmentPath = Join-Path $env:Temp "files.wixobj"
# cleanup any garbage on the system
Remove-Item -ErrorAction SilentlyContinue $wixFragmentPath -Force
Remove-Item -ErrorAction SilentlyContinue $wixObjProductPath -Force
Remove-Item -ErrorAction SilentlyContinue $wixObjFragmentPath -Force
$packageName = $productSemanticVersionWithName
if ($ProductNameSuffix) {
@ -3043,10 +3022,24 @@ function New-MSIPackage
}
Write-Log "verifying no new files have been added or removed..."
Start-NativeExecution -VerboseOutputOnError { & $wixPaths.wixHeatExePath dir $staging -dr VersionFolder -cg ApplicationFiles -ag -sfrag -srd -scom -sreg -out $wixFragmentPath -var env.ProductSourcePath -v}
$arguments = @{
IsPreview = $isPreview
ProductSourcePath = $staging
ProductName = $ProductName
ProductVersion = $ProductVersion
SimpleProductVersion = $simpleProductVersion
ProductSemanticVersion = $ProductSemanticVersion
ProductVersionWithName = $productVersionWithName
ProductProgFilesDir = $ProductProgFilesDir
FileArchitecture = $fileArchitecture
}
$buildArguments = New-MsiArgsArray -Argument $arguments
Start-NativeExecution -VerboseOutputOnError { & $wixPaths.wixHeatExePath dir $staging -dr VersionFolder -cg ApplicationFiles -ag -sfrag -srd -scom -sreg -out $wixFragmentPath -var var.ProductSourcePath $buildArguments -v}
# We are verifying that the generated $wixFragmentPath and $FilesWxsPath are functionally the same
Test-FileWxs -FilesWxsPath $FilesWxsPath -HeatFilesWxsPath $wixFragmentPath
Test-FileWxs -FilesWxsPath $FilesWxsPath -HeatFilesWxsPath $wixFragmentPath -FileArchitecture $fileArchitecture
if ($isPreview)
{
@ -3062,17 +3055,9 @@ function New-MSIPackage
Remove-Item -ErrorAction SilentlyContinue $wixObjFragmentPath -Force
}
Write-Log "running candle..."
Start-NativeExecution -VerboseOutputOnError { & $wixPaths.wixCandleExePath "$ProductWxsPath" "$FilesWxsPath" -out (Join-Path "$env:Temp" "\\") -ext WixUIExtension -ext WixUtilExtension -arch $ProductTargetArchitecture -dIsPreview="$isPreview" -v}
Write-Log "running light..."
# suppress ICE61, because we allow same version upgrades
# suppress ICE57, this suppresses an error caused by our shortcut not being installed per user
Start-NativeExecution -VerboseOutputOnError {& $wixPaths.wixLightExePath -sice:ICE61 -sice:ICE57 -out $msiLocationPath -pdbout $msiPdbLocationPath $wixObjProductPath $wixObjFragmentPath -ext WixUIExtension -ext WixUtilExtension }
Start-MsiBuild -WxsFile $ProductWxsPath, $FilesWxsPath -ProductTargetArchitecture $ProductTargetArchitecture -Argument $arguments -MsiLocationPath $msiLocationPath -MsiPdbLocationPath $msiPdbLocationPath
Remove-Item -ErrorAction SilentlyContinue $wixFragmentPath -Force
Remove-Item -ErrorAction SilentlyContinue $wixObjProductPath -Force
Remove-Item -ErrorAction SilentlyContinue $wixObjFragmentPath -Force
if ((Test-Path $msiLocationPath) -and (Test-Path $msiPdbLocationPath))
{
@ -3090,6 +3075,75 @@ function New-MSIPackage
}
}
function New-MsiArgsArray {
param(
[Parameter(Mandatory)]
[Hashtable]$Argument
)
$buildArguments = @()
foreach ($key in $Argument.Keys) {
$buildArguments += "-d$key=`"$($Argument.$key)`""
}
return $buildArguments
}
function Start-MsiBuild {
param(
[string[]] $WxsFile,
[string[]] $Extension = @('WixUIExtension', 'WixUtilExtension', 'WixBalExtension'),
[string] $ProductTargetArchitecture,
[Hashtable] $Argument,
[string] $MsiLocationPath,
[string] $MsiPdbLocationPath
)
$outDir = $env:Temp
$wixPaths = Get-WixPath
$extensionArgs = @()
foreach ($extensionName in $Extension) {
$extensionArgs += '-ext'
$extensionArgs += $extensionName
}
$buildArguments = New-MsiArgsArray -Argument $Argument
$objectPaths = @()
foreach ($file in $WxsFile) {
$fileName = [system.io.path]::GetFileNameWithoutExtension($file)
$objectPaths += Join-Path $outDir -ChildPath "${filename}.wixobj"
}
foreach ($file in $objectPaths) {
Remove-Item -ErrorAction SilentlyContinue $file -Force
Remove-Item -ErrorAction SilentlyContinue $file -Force
}
$resolvedWxsFiles = @()
foreach ($file in $WxsFile) {
$resolvedWxsFiles += (Resolve-Path -Path $file).ProviderPath
}
Write-Verbose "$resolvedWxsFiles" -Verbose
Write-Log "running candle..."
Start-NativeExecution -VerboseOutputOnError { & $wixPaths.wixCandleExePath $resolvedWxsFiles -out "$outDir\\" $extensionArgs -arch $ProductTargetArchitecture $buildArguments -v}
Write-Log "running light..."
# suppress ICE61, because we allow same version upgrades
# suppress ICE57, this suppresses an error caused by our shortcut not being installed per user
Start-NativeExecution -VerboseOutputOnError {& $wixPaths.wixLightExePath -sice:ICE61 -sice:ICE57 -out $msiLocationPath -pdbout $msiPdbLocationPath $objectPaths $extensionArgs }
foreach($file in $objectPaths)
{
Remove-Item -ErrorAction SilentlyContinue $file -Force
Remove-Item -ErrorAction SilentlyContinue $file -Force
}
}
<#
.Synopsis
Creates a Windows AppX MSIX package and assumes that the binaries are already built using 'Start-PSBuild'.
@ -3252,12 +3306,14 @@ function Test-FileWxs
# File describing the MSI file components generated by heat
[ValidateNotNullOrEmpty()]
[ValidateScript( {Test-Path $_})]
[string] $HeatFilesWxsPath
[string] $HeatFilesWxsPath,
[string] $FileArchitecture
)
# Update the fileArchitecture in our file to the actual value. Since, the heat file will have the actual value.
# Wix will update this automaticaly, but the output is not the same xml
$filesAssetString = (Get-Content -Raw -Path $FilesWxsPath).Replace('$(var.FileArchitecture)',$env:FileArchitecture)
$filesAssetString = (Get-Content -Raw -Path $FilesWxsPath).Replace('$(var.FileArchitecture)', $FileArchitecture)
[xml] $filesAssetXml = $filesAssetString
[xml] $newFilesAssetXml = $filesAssetString
@ -3318,7 +3374,6 @@ function Test-FileWxs
$newComponent = New-XmlElement -XmlDoc $newFilesAssetXml -LocalName 'Component' -Node $filesNode -PassThru -NamespaceUri 'http://schemas.microsoft.com/wix/2006/wi'
$componentId = New-WixId -Prefix 'cmp'
New-XmlAttribute -XmlDoc $newFilesAssetXml -Element $newComponent -Name 'Id' -Value $componentId
New-XmlAttribute -XmlDoc $newFilesAssetXml -Element $newComponent -Name 'Guid' -Value "{$(New-Guid)}"
# Crete new File in Component
$newFile = New-XmlElement -XmlDoc $newFilesAssetXml -LocalName 'File' -Node $newComponent -PassThru -NamespaceUri 'http://schemas.microsoft.com/wix/2006/wi'
New-XmlAttribute -XmlDoc $newFilesAssetXml -Element $newFile -Name 'Id' -Value (New-WixId -Prefix 'fil')