Skip to content

Commit 6edd67d

Browse files
authored
LT-20524: Resolve install directories in silent (/quiet) installs (#937)
* LT-20524: validate silent install directories Run the MSI directory-resolution actions in InstallExecuteSequence for UILevel < 4 so /quiet and /qb resolve the same app and data paths as /passive and full UI. While validating the fix, reconcile the WiX 6 projects and installer evidence scripts so the MSI and bundles can be built and exercised locally again. * LT-20524: drop redundant offline bundle extensions
1 parent e5c46ef commit 6edd67d

11 files changed

Lines changed: 125 additions & 24 deletions

FLExInstaller/Directory.Packages.props

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,13 @@
99
</PropertyGroup>
1010

1111
<ItemGroup Label="Installer Packages">
12+
<PackageVersion Include="System.Resources.Extensions" Version="9.0.16" />
13+
<PackageVersion Include="WixToolset.Bal.wixext" Version="6.0.2" />
1214
<PackageVersion Include="WixToolset.Dtf.CustomAction" Version="6.0.0" />
1315
<PackageVersion Include="WixToolset.Dtf.WindowsInstaller" Version="6.0.0" />
16+
<PackageVersion Include="WixToolset.Heat" Version="6.0.2" />
17+
<PackageVersion Include="WixToolset.NetFx.wixext" Version="6.0.2" />
18+
<PackageVersion Include="WixToolset.UI.wixext" Version="6.0.2" />
19+
<PackageVersion Include="WixToolset.Util.wixext" Version="6.0.2" />
1420
</ItemGroup>
1521
</Project>

FLExInstaller/wix6/FieldWorks.Bundle.wixproj

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -38,9 +38,9 @@
3838
</PropertyGroup>
3939

4040
<ItemGroup>
41-
<PackageReference Include="WixToolset.Bal.wixext" Version="6.0.2" />
42-
<PackageReference Include="WixToolset.Util.wixext" Version="6.0.2" />
43-
<PackageReference Include="WixToolset.NetFx.wixext" Version="6.0.2" />
41+
<PackageReference Include="WixToolset.Bal.wixext" />
42+
<PackageReference Include="WixToolset.Util.wixext" />
43+
<PackageReference Include="WixToolset.NetFx.wixext" />
4444
</ItemGroup>
4545

4646
<ItemGroup>

FLExInstaller/wix6/FieldWorks.Installer.wixproj

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,10 @@
1313
Installer validation:
1414
- Harvested inputs include many versionless resource/data files that trigger ICE60.
1515
- We intentionally allow downgrades (single-instance policy), which triggers ICE61.
16+
- Newtonsoft.Json is intentionally authored as both a private copy and a GAC assembly to match
17+
the legacy installer, which triggers ICE30 under WiX 6 validation.
1618
-->
17-
<SuppressIces>ICE60;ICE61</SuppressIces>
19+
<SuppressIces>ICE30;ICE60;ICE61</SuppressIces>
1820
</PropertyGroup>
1921

2022
<!--
@@ -74,10 +76,10 @@
7476
</PropertyGroup>
7577

7678
<ItemGroup>
77-
<PackageReference Include="WixToolset.UI.wixext" Version="6.0.2" />
78-
<PackageReference Include="WixToolset.Util.wixext" Version="6.0.2" />
79-
<PackageReference Include="WixToolset.NetFx.wixext" Version="6.0.2" />
80-
<PackageReference Include="WixToolset.Heat" Version="6.0.2" />
79+
<PackageReference Include="WixToolset.UI.wixext" />
80+
<PackageReference Include="WixToolset.Util.wixext" />
81+
<PackageReference Include="WixToolset.NetFx.wixext" />
82+
<PackageReference Include="WixToolset.Heat" />
8183
</ItemGroup>
8284

8385
<ItemGroup>

FLExInstaller/wix6/FieldWorks.OfflineBundle.wixproj

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -38,9 +38,9 @@
3838
</PropertyGroup>
3939

4040
<ItemGroup>
41-
<PackageReference Include="WixToolset.Bal.wixext" Version="6.0.2" />
42-
<PackageReference Include="WixToolset.Util.wixext" Version="6.0.2" />
43-
<PackageReference Include="WixToolset.NetFx.wixext" Version="6.0.2" />
41+
<PackageReference Include="WixToolset.Bal.wixext" />
42+
<PackageReference Include="WixToolset.Util.wixext" />
43+
<PackageReference Include="WixToolset.NetFx.wixext" />
4444
</ItemGroup>
4545

4646
<ItemGroup>

FLExInstaller/wix6/Shared/Base/Framework.wxs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,23 @@
6767
<Custom Action="DeleteRegistryVersionNumber" Before="RemoveRegistryValues" Condition="(NOT UPGRADINGPRODUCTCODE) AND (REMOVE=&quot;ALL&quot;)" />
6868
<Custom Action="CheckPatchValue" Before="CheckUpgradeValue" Condition="PATCHNEWSUMMARYSUBJECT=&quot;Small Update Patch&quot;" />
6969
<Custom Action="CheckUpgradeValue" After="InstallFinalize" Condition="WIX_UPGRADE_DETECTED" />
70+
<!-- LT-20524: The InstallUISequence does not run for silent (/quiet, /qn) or basic (/qb) installs
71+
(UILevel &lt; 4), so the directory-resolution actions below must also run here; otherwise
72+
APPFOLDER/DATAFOLDER/HARVESTDATAFOLDER stay unset and files (including the ICU data that
73+
ICU_DATA points at) install to the wrong locations. Reduced (/passive, UILevel 4) and full
74+
UI installs continue to resolve these in the InstallUISequence, so the UILevel guard keeps
75+
this from overriding a user-chosen path. VerifyDataPath populates REGDATAFOLDER (used by the
76+
conditions below) and always returns Success, so it is safe in a silent install. -->
77+
<Custom Action="SetDefDataFolder" After="FindRelatedProducts" Condition="UILevel &lt; 4" />
78+
<Custom Action="VerifyDataPath" After="SetDefDataFolder" Condition="UILevel &lt; 4" />
79+
<Custom Action="UseDefAppFolder" After="AppSearch" Condition="(UILevel &lt; 4) and (NOT REGAPPFOLDER) and (NOT OVRAPPFOLDER)" />
80+
<Custom Action="UseOvrAppFolder" After="AppSearch" Condition="(UILevel &lt; 4) and (NOT REGAPPFOLDER) and (OVRAPPFOLDER)" />
81+
<Custom Action="UseRegAppFolder" After="AppSearch" Condition="(UILevel &lt; 4) and (REGAPPFOLDER)" />
82+
<Custom Action="UseDefDataFolder" After="AppSearch" Condition="(UILevel &lt; 4) and (NOT REGDATAFOLDER) and (NOT OVRDATAFOLDER)" />
83+
<Custom Action="UseOvrDataFolder" After="AppSearch" Condition="(UILevel &lt; 4) and (NOT REGDATAFOLDER) and (OVRDATAFOLDER)" />
84+
<Custom Action="UseRegDataFolder" After="AppSearch" Condition="(UILevel &lt; 4) and (REGDATAFOLDER)" />
85+
<Custom Action="UseDefHarvestDataFolder" After="AppSearch" Condition="(UILevel &lt; 4) and (NOT OVRHARVESTDATAFOLDER)" />
86+
<Custom Action="UseOvrHarvestDataFolder" After="AppSearch" Condition="(UILevel &lt; 4) and (OVRHARVESTDATAFOLDER)" />
7087
<?include ../Common/CustomActionSteps.wxi?>
7188
</InstallExecuteSequence>
7289

FLExInstaller/wix6/Shared/Common/CustomComponents.wxi

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,12 +67,14 @@
6767
<Component Id="NewtonsoftJsonApp" Guid="{B8A47C61-2E90-4D1A-9F4E-7C3B5A682D01}">
6868
<File Id="NewtonsoftJsonFileApp"
6969
Name="Newtonsoft.Json.dll"
70+
ShortName="NJSONAPP.DLL"
7071
Source="$(var.MASTERBUILDDIR)\Newtonsoft.Json.dll"
7172
KeyPath="yes" />
7273
</Component>
7374
<Component Id="NewtonsoftJsonGac" Guid="*">
7475
<File Id="NewtonsoftJsonFileGac"
7576
Name="Newtonsoft.Json.dll"
77+
ShortName="NJSONGAC.DLL"
7678
Source="$(var.MASTERBUILDDIR)\Newtonsoft.Json.dll"
7779
KeyPath="yes"
7880
Assembly=".net" />

FLExInstaller/wix6/Shared/CustomActions/CustomActions/CustomAction.cs

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -220,9 +220,17 @@ private static string GetDataDirFromRegistry(string path, string valueName, Sess
220220
try
221221
{
222222
if (RegistryU.KeyExists(dataPathKey))
223-
projPath = RegistryU.GetKey("HKLM", "SOFTWARE\\" + path).GetValue(valueName).ToString();
223+
{
224+
var value = RegistryU.GetKey("HKLM", "SOFTWARE\\" + path).GetValue(valueName);
225+
if (value != null)
226+
projPath = value.ToString();
227+
}
224228
if (RegistryU.KeyExists(dataPathKeyWow))
225-
projPath = RegistryU.GetKey("HKLM", "SOFTWARE\\Wow6432Node\\" + path).GetValue(valueName).ToString();
229+
{
230+
var value = RegistryU.GetKey("HKLM", "SOFTWARE\\Wow6432Node\\" + path).GetValue(valueName);
231+
if (value != null)
232+
projPath = value.ToString();
233+
}
226234
}
227235
catch (Exception ex)
228236
{

FLExInstaller/wix6/Shared/CustomActions/CustomActions/CustomActions.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
<Content Include="CustomAction.config" CopyToOutputDirectory="PreserveNewest" />
1111
</ItemGroup>
1212
<ItemGroup>
13+
<PackageReference Include="System.Resources.Extensions" />
1314
<PackageReference Include="WixToolset.Dtf.CustomAction" />
1415
<PackageReference Include="WixToolset.Dtf.WindowsInstaller" />
1516
</ItemGroup>

scripts/Agent/Collect-InstallerSnapshot.ps1

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -227,4 +227,4 @@ $json = $snapshot | ConvertTo-Json -Depth 10
227227
Set-Content -LiteralPath $outPath -Value $json -Encoding UTF8
228228

229229
Write-Output "Wrote snapshot: $outPath"
230-
Write-Output ("UninstallEntries: {0}, RegistryRoots: {1}, Files: {2}" -f $snapshot.UninstallEntries.Count, $snapshot.Registry.Count, $snapshot.Files.Count)
230+
Write-Output ("UninstallEntries: {0}, RegistryRoots: {1}, Files: {2}" -f @($snapshot.UninstallEntries).Count, @($snapshot.Registry).Count, @($snapshot.Files).Count)

scripts/Agent/Compare-InstallerSnapshots.ps1

Lines changed: 27 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -29,10 +29,10 @@ function Read-Snapshot {
2929
}
3030

3131
function To-StringSet {
32-
param([Parameter(Mandatory = $true)][object[]]$Items)
32+
param([Parameter(Mandatory = $true)][AllowEmptyCollection()][object[]]$Items)
3333
$set = New-Object 'System.Collections.Generic.HashSet[string]' ([System.StringComparer]::OrdinalIgnoreCase)
3434
foreach ($item in $Items) { $null = $set.Add([string]$item) }
35-
return $set
35+
return ,$set
3636
}
3737

3838
function Diff-Sets {
@@ -54,6 +54,28 @@ function Diff-Sets {
5454
return [pscustomobject]@{ Added = $added; Removed = $removed }
5555
}
5656

57+
function ConvertTo-PropertyMap {
58+
param([Parameter(Mandatory = $false)]$Value)
59+
60+
$map = @{}
61+
if ($null -eq $Value) {
62+
return $map
63+
}
64+
65+
if ($Value -is [System.Collections.IDictionary]) {
66+
foreach ($key in $Value.Keys) {
67+
$map[[string]$key] = $Value[$key]
68+
}
69+
return $map
70+
}
71+
72+
foreach ($property in $Value.PSObject.Properties) {
73+
$map[[string]$property.Name] = $property.Value
74+
}
75+
76+
return $map
77+
}
78+
5779
$before = Read-Snapshot -Path $BeforeSnapshotPath
5880
$after = Read-Snapshot -Path $AfterSnapshotPath
5981

@@ -100,9 +122,9 @@ foreach ($k in $afterRegByPath.Keys) { $null = $allRegPaths.Add($k) }
100122

101123
foreach ($path in ($allRegPaths | Sort-Object)) {
102124
$beforeValues = @{}
103-
if ($beforeRegByPath.ContainsKey($path)) { $beforeValues = $beforeRegByPath[$path].Values }
125+
if ($beforeRegByPath.ContainsKey($path)) { $beforeValues = ConvertTo-PropertyMap -Value $beforeRegByPath[$path].Values }
104126
$afterValues = @{}
105-
if ($afterRegByPath.ContainsKey($path)) { $afterValues = $afterRegByPath[$path].Values }
127+
if ($afterRegByPath.ContainsKey($path)) { $afterValues = ConvertTo-PropertyMap -Value $afterRegByPath[$path].Values }
106128

107129
$allNames = New-Object System.Collections.Generic.HashSet[string] ([System.StringComparer]::OrdinalIgnoreCase)
108130
foreach ($n in $beforeValues.Keys) { $null = $allNames.Add([string]$n) }
@@ -123,7 +145,7 @@ foreach ($path in ($allRegPaths | Sort-Object)) {
123145
}
124146
if ([string]$bn -ne [string]$an) {
125147
$regDiffCount++
126-
if ($regDiffCount -le $MaxListItems) { $reportLines.Add(" ~ $path\\$n: '$bn' -> '$an'") }
148+
if ($regDiffCount -le $MaxListItems) { $reportLines.Add(" ~ ${path}\\${n}: '$bn' -> '$an'") }
127149
}
128150
}
129151
}

0 commit comments

Comments
 (0)