mirror of
https://github.com/PowerShell/PowerShell
synced 2026-06-08 12:12:50 +00:00
MSI: Make sure that file components are patchable (#6303)
MSI: Make sure that file components are patchable - avoid changing names and guids of components between builds as this prevents patch generation - This required submitting the file generated by heat - add code to make sure the generated file is not out of date
This commit is contained in:
+17
-16
@@ -16,6 +16,7 @@
|
||||
<?define ProductSemanticVersionWithNameAndOptionalArchitecture = "$(var.ProductName) $(env.ProductSemanticVersion) ($(sys.BUILDARCH))"?>
|
||||
<?define ExplorerContextMenuDialogText = "&$(var.ProductName) $(env.ProductSemanticVersion) ($(sys.BUILDARCH))"?>
|
||||
<?endif?>
|
||||
<?define ProductDirectoryName = "$(env.ProductDirectoryName)" ?>
|
||||
<?define ProductVersion = "$(env.ProductVersion)" ?>
|
||||
<?define ProductSemanticVersion = "$(env.ProductSemanticVersion)" ?>
|
||||
<?define ProductVersionWithName = "$(var.ProductName)_$(var.ProductVersion)"?>
|
||||
@@ -41,13 +42,13 @@
|
||||
<WixVariable Id="WixUIInfoIco" Value="assets\WixUIInfoIco.bmp" />
|
||||
<Property Id="WIXUI_EXITDIALOGOPTIONALCHECKBOXTEXT" Value="Open $(env.ProductName)" />
|
||||
<!-- Default value of Checkbox of starting PowerShell after installation -->
|
||||
<Property Id="WixShellExecTarget" Value="[$(var.ProductVersionWithName)]pwsh.exe"/>
|
||||
<Property Id="WixShellExecTarget" Value="[$(var.ProductDirectoryName)]pwsh.exe"/>
|
||||
<CustomAction Id="LaunchApplication" BinaryKey="WixCA" DllEntry="WixShellExec" Impersonate="yes" />
|
||||
|
||||
<SetProperty Id="RegisterManifest"
|
||||
Before="RegisterManifest"
|
||||
Sequence="execute"
|
||||
Value=""[$(var.ProductVersionWithName)]pwsh.exe" -NoProfile -ExecutionPolicy Bypass -File "[$(var.ProductVersionWithName)]RegisterManifest.ps1"" />
|
||||
Value=""[$(var.ProductDirectoryName)]pwsh.exe" -NoProfile -ExecutionPolicy Bypass -File "[$(var.ProductDirectoryName)]RegisterManifest.ps1"" />
|
||||
<CustomAction Id="RegisterManifest"
|
||||
BinaryKey="WixCA"
|
||||
DllEntry="CAQuietExec"
|
||||
@@ -57,7 +58,7 @@
|
||||
<SetProperty Id="EnablePSRemoting"
|
||||
Before="EnablePSRemoting"
|
||||
Sequence="execute"
|
||||
Value=""[$(var.ProductVersionWithName)]pwsh.exe" -NoProfile -ExecutionPolicy Bypass -Command "Enable-PSRemoting"" />
|
||||
Value=""[$(var.ProductDirectoryName)]pwsh.exe" -NoProfile -ExecutionPolicy Bypass -Command "Enable-PSRemoting"" />
|
||||
<CustomAction Id="EnablePSRemoting"
|
||||
BinaryKey="WixCA"
|
||||
DllEntry="CAQuietExec"
|
||||
@@ -109,7 +110,7 @@
|
||||
<UIRef Id="CustomWixUI_InstallDir" />
|
||||
<!-- Features are mandatory. Need At Least One. -->
|
||||
<Feature Id="ProductFeature" Title="PowerShell" Level="1">
|
||||
<ComponentGroupRef Id="$(var.ProductVersionWithName)"/>
|
||||
<ComponentGroupRef Id="$(var.ProductDirectoryName)"/>
|
||||
<ComponentRef Id="ProductVersionFolder"/>
|
||||
<ComponentRef Id="ApplicationProgramsMenuShortcut"/>
|
||||
<ComponentRef Id="RegistryEntries"/>
|
||||
@@ -141,7 +142,7 @@
|
||||
<Directory Id="TARGETDIR" Name="SourceDir">
|
||||
<Directory Id="$(var.ProductProgFilesDir)">
|
||||
<Directory Id="INSTALLFOLDER" Name="PowerShell">
|
||||
<Directory Id="$(var.ProductVersionWithName)" Name="$(var.ProductSemanticVersion)">
|
||||
<Directory Id="$(var.ProductDirectoryName)" Name="$(var.ProductSemanticVersion)">
|
||||
<Component Id="ProductVersionFolder" Guid="{e1a7f05e-0cd6-4227-80a8-e4fb311f045c}">
|
||||
<CreateFolder/>
|
||||
</Component>
|
||||
@@ -153,7 +154,7 @@
|
||||
</RegistryKey>
|
||||
<!-- register ourselves in application registry so can be started using just Win+R `pwsh.exe` -->
|
||||
<RegistryKey Root="HKLM" Key="Software\Microsoft\Windows\CurrentVersion\App Paths\pwsh.exe" ForceCreateOnInstall="yes" ForceDeleteOnUninstall="yes">
|
||||
<RegistryValue Type="string" Value="[$(var.ProductVersionWithName)]pwsh.exe"/>
|
||||
<RegistryValue Type="string" Value="[$(var.ProductDirectoryName)]pwsh.exe"/>
|
||||
</RegistryKey>
|
||||
</Component>
|
||||
<!-- add ourselves to %PATH% so pwsh.exe can be started from Windows PowerShell or cmd.exe -->
|
||||
@@ -167,42 +168,42 @@
|
||||
<!-- When clicking on background in Explorer -->
|
||||
<RegistryKey Root="HKCR" Key="Directory\Background\shell\$(var.ProductName)$(env.ProductSemanticVersion)$(sys.BUILDARCH)">
|
||||
<RegistryValue Type="string" Name="MUIVerb" Value="$(var.ExplorerContextMenuDialogText)"/>
|
||||
<RegistryValue Type="string" Name="Icon" Value="[$(var.ProductVersionWithName)]assets\Powershell_black.ico"/>
|
||||
<RegistryValue Type="string" Name="Icon" Value="[$(var.ProductDirectoryName)]assets\Powershell_black.ico"/>
|
||||
<RegistryValue Type="string" Name="ExtendedSubCommandsKey" Value="Directory\ContextMenus\$(var.ProductName)$(env.ProductSemanticVersion)$(sys.BUILDARCH)"/>
|
||||
</RegistryKey>
|
||||
<!-- When clicking on Drive in Explorer -->
|
||||
<RegistryKey Root="HKCR" Key="Drive\shell\$(var.ProductName)$(env.ProductSemanticVersion)$(sys.BUILDARCH)">
|
||||
<RegistryValue Type="string" Name="MUIVerb" Value="$(var.ExplorerContextMenuDialogText)"/>
|
||||
<RegistryValue Type="string" Name="Icon" Value="[$(var.ProductVersionWithName)]assets\Powershell_black.ico"/>
|
||||
<RegistryValue Type="string" Name="Icon" Value="[$(var.ProductDirectoryName)]assets\Powershell_black.ico"/>
|
||||
<RegistryValue Type="string" Name="ExtendedSubCommandsKey" Value="Directory\ContextMenus\$(var.ProductName)$(env.ProductSemanticVersion)$(sys.BUILDARCH)"/>
|
||||
</RegistryKey>
|
||||
<!-- When clicking on Desktop background in Explorer -->
|
||||
<RegistryKey Root="HKCR" Key="DesktopBackground\shell\$(var.ProductName)$(env.ProductSemanticVersion)$(sys.BUILDARCH)">
|
||||
<RegistryValue Type="string" Name="MUIVerb" Value="$(var.ExplorerContextMenuDialogText)"/>
|
||||
<RegistryValue Type="string" Name="Icon" Value="[$(var.ProductVersionWithName)]assets\Powershell_black.ico"/>
|
||||
<RegistryValue Type="string" Name="Icon" Value="[$(var.ProductDirectoryName)]assets\Powershell_black.ico"/>
|
||||
<RegistryValue Type="string" Name="ExtendedSubCommandsKey" Value="Directory\ContextMenus\$(var.ProductName)$(env.ProductSemanticVersion)$(sys.BUILDARCH)"/>
|
||||
</RegistryKey>
|
||||
<!-- When clicking on folder in Explorer -->
|
||||
<RegistryKey Root="HKCR" Key="Directory\shell\$(var.ProductName)$(env.ProductSemanticVersion)$(sys.BUILDARCH)">
|
||||
<RegistryValue Type="string" Name="MUIVerb" Value="$(var.ExplorerContextMenuDialogText)"/>
|
||||
<RegistryValue Type="string" Name="Icon" Value="[$(var.ProductVersionWithName)]assets\Powershell_black.ico"/>
|
||||
<RegistryValue Type="string" Name="Icon" Value="[$(var.ProductDirectoryName)]assets\Powershell_black.ico"/>
|
||||
<RegistryValue Type="string" Name="ExtendedSubCommandsKey" Value="Directory\ContextMenus\$(var.ProductName)$(env.ProductSemanticVersion)$(sys.BUILDARCH)"/>
|
||||
</RegistryKey>
|
||||
<!-- Sub menus to open PowerShell at the current location either as a normal shell or as Administrator -->
|
||||
<RegistryKey Root="HKCR" Key="Directory\ContextMenus\$(var.ProductName)$(env.ProductSemanticVersion)$(sys.BUILDARCH)\shell\open">
|
||||
<RegistryValue Type="string" Name="MUIVerb" Value="$(var.ExplorerContextSubMenuDialogText)"/>
|
||||
<RegistryValue Type="string" Name="Icon" Value="[$(var.ProductVersionWithName)]assets\Powershell_black.ico"/>
|
||||
<RegistryValue Type="string" Name="Icon" Value="[$(var.ProductDirectoryName)]assets\Powershell_black.ico"/>
|
||||
</RegistryKey>
|
||||
<RegistryKey Root="HKCR" Key="Directory\ContextMenus\$(var.ProductName)$(env.ProductSemanticVersion)$(sys.BUILDARCH)\shell\open\command">
|
||||
<RegistryValue Type="string" Value="[$(var.ProductVersionWithName)]pwsh.exe -NoExit -Command Set-Location -LiteralPath '%V'"/>
|
||||
<RegistryValue Type="string" Value="[$(var.ProductDirectoryName)]pwsh.exe -NoExit -Command Set-Location -LiteralPath '%V'"/>
|
||||
</RegistryKey>
|
||||
<RegistryKey Root="HKCR" Key="Directory\ContextMenus\$(var.ProductName)$(env.ProductSemanticVersion)$(sys.BUILDARCH)\shell\runas">
|
||||
<RegistryValue Type="string" Name="MUIVerb" Value="$(var.ExplorerContextSubMenuElevatedDialogText)"/>
|
||||
<RegistryValue Type="string" Name="Icon" Value="[$(var.ProductVersionWithName)]assets\Powershell_black.ico"/>
|
||||
<RegistryValue Type="string" Name="Icon" Value="[$(var.ProductDirectoryName)]assets\Powershell_black.ico"/>
|
||||
<RegistryValue Type="string" Value="" Name="HasLUAShield"/>
|
||||
</RegistryKey>
|
||||
<RegistryKey Root="HKCR" Key="Directory\ContextMenus\$(var.ProductName)$(env.ProductSemanticVersion)$(sys.BUILDARCH)\shell\runas\command">
|
||||
<RegistryValue Type="string" Value="[$(var.ProductVersionWithName)]pwsh.exe -NoExit -Command Set-Location -LiteralPath '%V'"/>
|
||||
<RegistryValue Type="string" Value="[$(var.ProductDirectoryName)]pwsh.exe -NoExit -Command Set-Location -LiteralPath '%V'"/>
|
||||
</RegistryKey>
|
||||
</Component>
|
||||
</Directory>
|
||||
@@ -214,8 +215,8 @@
|
||||
<Shortcut Id="PowerShell_ProgramsMenuShortcut"
|
||||
Name="$(var.ProductSemanticVersionWithNameAndOptionalArchitecture)"
|
||||
Description="$(var.ProductSemanticVersionWithNameAndOptionalArchitecture)"
|
||||
Target="[$(var.ProductVersionWithName)]pwsh.exe"
|
||||
WorkingDirectory="$(var.ProductVersionWithName)"
|
||||
Target="[$(var.ProductDirectoryName)]pwsh.exe"
|
||||
WorkingDirectory="$(var.ProductDirectoryName)"
|
||||
Icon = "PowerShellExe.ico" />
|
||||
<RemoveFolder Id="ApplicationProgramsFolder" On="uninstall"/>
|
||||
<!-- HKMU is HKLM when installing perMachine and HKCU when installing perUser-->
|
||||
|
||||
+2406
File diff suppressed because it is too large
Load Diff
@@ -2050,6 +2050,11 @@ function New-MSIPackage
|
||||
[ValidateScript( {Test-Path $_})]
|
||||
[string] $ProductWxsPath = "$PSScriptRoot\..\..\assets\Product.wxs",
|
||||
|
||||
# File describing the MSI file components
|
||||
[ValidateNotNullOrEmpty()]
|
||||
[ValidateScript( {Test-Path $_})]
|
||||
[string] $FilesWxsPath = "$PSScriptRoot\..\..\assets\Files.wxs",
|
||||
|
||||
# Path to Assets folder containing artifacts such as icons, images
|
||||
[ValidateNotNullOrEmpty()]
|
||||
[ValidateScript( {Test-Path $_})]
|
||||
@@ -2100,11 +2105,13 @@ function New-MSIPackage
|
||||
|
||||
$productVersionWithName = $ProductName + '_' + $ProductVersion
|
||||
$productSemanticVersionWithName = $ProductName + '-' + $ProductSemanticVersion
|
||||
$productDirectoryName = 'PowerShell_6'
|
||||
|
||||
Write-Verbose "Create MSI for Product $productSemanticVersionWithName"
|
||||
|
||||
[Environment]::SetEnvironmentVariable("ProductSourcePath", $ProductSourcePath, "Process")
|
||||
# These variables are used by Product.wxs in assets directory
|
||||
[Environment]::SetEnvironmentVariable("ProductDirectoryName", $productDirectoryName, "Process")
|
||||
[Environment]::SetEnvironmentVariable("ProductName", $ProductName, "Process")
|
||||
[Environment]::SetEnvironmentVariable("ProductCode", $ProductCode, "Process")
|
||||
[Environment]::SetEnvironmentVariable("ProductVersion", $ProductVersion, "Process")
|
||||
@@ -2130,7 +2137,7 @@ function New-MSIPackage
|
||||
|
||||
$wixFragmentPath = Join-Path $env:Temp "Fragment.wxs"
|
||||
$wixObjProductPath = Join-Path $env:Temp "Product.wixobj"
|
||||
$wixObjFragmentPath = Join-Path $env:Temp "Fragment.wixobj"
|
||||
$wixObjFragmentPath = Join-Path $env:Temp "files.wixobj"
|
||||
|
||||
# cleanup any garbage on the system
|
||||
Remove-Item -ErrorAction SilentlyContinue $wixFragmentPath -Force
|
||||
@@ -2149,11 +2156,12 @@ function New-MSIPackage
|
||||
Write-Error -Message "Package already exists, use -Force to overwrite, path: $msiLocationPath" -ErrorAction Stop
|
||||
}
|
||||
|
||||
log "running heat..."
|
||||
Start-NativeExecution -VerboseOutputOnError { & $wixHeatExePath dir $ProductSourcePath -dr $productVersionWithName -cg $productVersionWithName -gg -sfrag -srd -scom -sreg -out $wixFragmentPath -var env.ProductSourcePath -v}
|
||||
log "verifying no new files have been added or removed..."
|
||||
Start-NativeExecution -VerboseOutputOnError { & $wixHeatExePath dir $ProductSourcePath -dr $productDirectoryName -cg $productDirectoryName -gg -sfrag -srd -scom -sreg -out $wixFragmentPath -var env.ProductSourcePath -v}
|
||||
Test-FileWxs -FilesWxsPath $FilesWxsPath -HeatFilesWxsPath $wixFragmentPath
|
||||
|
||||
log "running candle..."
|
||||
Start-NativeExecution -VerboseOutputOnError { & $wixCandleExePath "$ProductWxsPath" "$wixFragmentPath" -out (Join-Path "$env:Temp" "\\") -ext WixUIExtension -ext WixUtilExtension -arch $ProductTargetArchitecture -v}
|
||||
Start-NativeExecution -VerboseOutputOnError { & $wixCandleExePath "$ProductWxsPath" "$FilesWxsPath" -out (Join-Path "$env:Temp" "\\") -ext WixUIExtension -ext WixUtilExtension -arch $ProductTargetArchitecture -v}
|
||||
|
||||
log "running light..."
|
||||
# suppress ICE61, because we allow same version upgrades
|
||||
@@ -2184,6 +2192,66 @@ function New-MSIPackage
|
||||
}
|
||||
}
|
||||
|
||||
# verify no files have been added or removed
|
||||
# if so, write an error with details
|
||||
function Test-FileWxs
|
||||
{
|
||||
param
|
||||
(
|
||||
# File describing the MSI file components from the asset folder
|
||||
[ValidateNotNullOrEmpty()]
|
||||
[ValidateScript( {Test-Path $_})]
|
||||
[string] $FilesWxsPath = "$PSScriptRoot\..\..\assets\Files.wxs",
|
||||
|
||||
# File describing the MSI file components generated by heat
|
||||
[ValidateNotNullOrEmpty()]
|
||||
[ValidateScript( {Test-Path $_})]
|
||||
[string] $HeatFilesWxsPath
|
||||
)
|
||||
|
||||
[xml] $filesAssetXml = Get-Content -Raw -Path $FilesWxsPath
|
||||
[xml] $heatFilesXml = Get-Content -Raw -Path $HeatFilesWxsPath
|
||||
$assetFiles = $filesAssetXml.GetElementsByTagName('File')
|
||||
$heatFiles = $heatFilesXml.GetElementsByTagName('File')
|
||||
$indexedHeatFiles = @()
|
||||
|
||||
# Index the list of files generated by heat
|
||||
foreach($file in $heatFiles)
|
||||
{
|
||||
$indexedHeatFiles += $file.Source
|
||||
}
|
||||
|
||||
# Index the files from the asset wxs
|
||||
# and verify that no files have been removed.
|
||||
$passed = $true
|
||||
$indexedAssetFiles = @()
|
||||
foreach($file in $assetFiles)
|
||||
{
|
||||
$name = $file.Source
|
||||
if($indexedHeatFiles -inotcontains $name)
|
||||
{
|
||||
$passed = $false
|
||||
Write-Warning "{$name} is no longer in product and should be removed from {$FilesWxsPath}"
|
||||
}
|
||||
$indexedAssetFiles += $name
|
||||
}
|
||||
|
||||
# verify that no files have been added.
|
||||
foreach($file in $indexedHeatFiles)
|
||||
{
|
||||
if($indexedAssetFiles -inotcontains $file)
|
||||
{
|
||||
$passed = $false
|
||||
Write-Warning "new file {$file} need to be added to {$FilesWxsPath}"
|
||||
}
|
||||
}
|
||||
|
||||
if(!$passed)
|
||||
{
|
||||
throw "Current files to not match {$FilesWxsPath}"
|
||||
}
|
||||
}
|
||||
|
||||
# Builds coming out of this project can have version number as 'a.b.c' OR 'a.b.c-d-f'
|
||||
# This function converts the above version into major.minor[.build[.revision]] format
|
||||
function Get-PackageVersionAsMajorMinorBuildRevision
|
||||
|
||||
Reference in New Issue
Block a user