aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCharles Baker <charles@juicelabs.co>2024-10-24 13:13:26 +1300
committerRob Mensching <rob@firegiant.com>2026-01-02 16:21:49 -0800
commitcd46cf04280d9b27fb271393a7aeb8289fe9c43c (patch)
treea69ccd128100a24ec4501db0c10cd794e583cdc6
parent2a58247b62bdea7c829ca643812faa7665f39a73 (diff)
downloadwix-robmen/add-display-files-in-use-dialog-attribute.tar.gz
wix-robmen/add-display-files-in-use-dialog-attribute.tar.bz2
wix-robmen/add-display-files-in-use-dialog-attribute.zip
Add bal:DisplayFilesInUseDialogCondition to disable Files In Use dialogrobmen/add-display-files-in-use-dialog-attribute
Disabling display skips showing the "Files In Use" dialog and returning a result as if the user had chosen to ignore the dialog and reboot in the case of files that were unable to be replaced.
-rw-r--r--src/api/burn/WixToolset.BootstrapperApplicationApi/IPackageInfo.cs5
-rw-r--r--src/api/burn/WixToolset.BootstrapperApplicationApi/PackageInfo.cs4
-rw-r--r--src/api/burn/balutil/balinfo.cpp4
-rw-r--r--src/api/burn/balutil/inc/balinfo.h1
-rw-r--r--src/ext/Bal/stdbas/WixStandardBootstrapperApplication.cpp52
-rw-r--r--src/ext/Bal/test/WixToolsetTest.BootstrapperApplications/BalExtensionFixture.cs39
-rw-r--r--src/ext/Bal/test/WixToolsetTest.BootstrapperApplications/InternalUIBAFixture.cs3
-rw-r--r--src/ext/Bal/test/WixToolsetTest.BootstrapperApplications/TestData/Overridable/WrongCaseBundle.wxs2
-rw-r--r--src/ext/Bal/test/WixToolsetTest.BootstrapperApplications/TestData/WixIuiBa/IuibaWarnings.wxs2
-rw-r--r--src/ext/Bal/test/WixToolsetTest.BootstrapperApplications/TestData/WixStdBa/DisplayFilesInUseDialogConditionBundle.wxs12
-rw-r--r--src/ext/Bal/wixext/BalBurnBackendExtension.cs22
-rw-r--r--src/ext/Bal/wixext/BalCompiler.cs14
-rw-r--r--src/ext/Bal/wixext/BalWarnings.cs6
-rw-r--r--src/ext/Bal/wixext/Symbols/WixBalPackageInfoSymbol.cs8
-rw-r--r--src/xsd/bal.xsd15
15 files changed, 169 insertions, 20 deletions
diff --git a/src/api/burn/WixToolset.BootstrapperApplicationApi/IPackageInfo.cs b/src/api/burn/WixToolset.BootstrapperApplicationApi/IPackageInfo.cs
index e2512584..9b5e74cb 100644
--- a/src/api/burn/WixToolset.BootstrapperApplicationApi/IPackageInfo.cs
+++ b/src/api/burn/WixToolset.BootstrapperApplicationApi/IPackageInfo.cs
@@ -28,6 +28,11 @@ namespace WixToolset.BootstrapperApplicationApi
28 string DisplayInternalUICondition { get; } 28 string DisplayInternalUICondition { get; }
29 29
30 /// <summary> 30 /// <summary>
31 /// The authored bal:DisplayFilesInUseDialogCondition.
32 /// </summary>
33 string DisplayFilesInUseDialogCondition { get; }
34
35 /// <summary>
31 /// The package's display name. 36 /// The package's display name.
32 /// </summary> 37 /// </summary>
33 string DisplayName { get; } 38 string DisplayName { get; }
diff --git a/src/api/burn/WixToolset.BootstrapperApplicationApi/PackageInfo.cs b/src/api/burn/WixToolset.BootstrapperApplicationApi/PackageInfo.cs
index e835f9ea..81a8869f 100644
--- a/src/api/burn/WixToolset.BootstrapperApplicationApi/PackageInfo.cs
+++ b/src/api/burn/WixToolset.BootstrapperApplicationApi/PackageInfo.cs
@@ -121,6 +121,9 @@ namespace WixToolset.BootstrapperApplicationApi
121 public string DisplayInternalUICondition { get; internal set; } 121 public string DisplayInternalUICondition { get; internal set; }
122 122
123 /// <inheritdoc/> 123 /// <inheritdoc/>
124 public string DisplayFilesInUseDialogCondition { get; internal set; }
125
126 /// <inheritdoc/>
124 public string ProductCode { get; internal set; } 127 public string ProductCode { get; internal set; }
125 128
126 /// <inheritdoc/> 129 /// <inheritdoc/>
@@ -363,6 +366,7 @@ namespace WixToolset.BootstrapperApplicationApi
363 var package = (PackageInfo)ipackage; 366 var package = (PackageInfo)ipackage;
364 367
365 package.DisplayInternalUICondition = BootstrapperApplicationData.GetAttribute(node, "DisplayInternalUICondition"); 368 package.DisplayInternalUICondition = BootstrapperApplicationData.GetAttribute(node, "DisplayInternalUICondition");
369 package.DisplayFilesInUseDialogCondition = BootstrapperApplicationData.GetAttribute(node, "DisplayFilesInUseDialogCondition");
366 } 370 }
367 371
368 nodes = root.Select("/p:BootstrapperApplicationData/p:WixPrereqInformation", namespaceManager); 372 nodes = root.Select("/p:BootstrapperApplicationData/p:WixPrereqInformation", namespaceManager);
diff --git a/src/api/burn/balutil/balinfo.cpp b/src/api/burn/balutil/balinfo.cpp
index 38c4bd18..ff0dfd9f 100644
--- a/src/api/burn/balutil/balinfo.cpp
+++ b/src/api/burn/balutil/balinfo.cpp
@@ -291,6 +291,7 @@ DAPI_(void) BalInfoUninitialize(
291 ReleaseStr(pBundle->packages.rgPackages[i].sczDescription); 291 ReleaseStr(pBundle->packages.rgPackages[i].sczDescription);
292 ReleaseStr(pBundle->packages.rgPackages[i].sczId); 292 ReleaseStr(pBundle->packages.rgPackages[i].sczId);
293 ReleaseStr(pBundle->packages.rgPackages[i].sczDisplayInternalUICondition); 293 ReleaseStr(pBundle->packages.rgPackages[i].sczDisplayInternalUICondition);
294 ReleaseStr(pBundle->packages.rgPackages[i].sczDisplayFilesInUseDialogCondition);
294 ReleaseStr(pBundle->packages.rgPackages[i].sczProductCode); 295 ReleaseStr(pBundle->packages.rgPackages[i].sczProductCode);
295 ReleaseStr(pBundle->packages.rgPackages[i].sczUpgradeCode); 296 ReleaseStr(pBundle->packages.rgPackages[i].sczUpgradeCode);
296 ReleaseStr(pBundle->packages.rgPackages[i].sczVersion); 297 ReleaseStr(pBundle->packages.rgPackages[i].sczVersion);
@@ -517,6 +518,9 @@ static HRESULT ParseBalPackageInfoFromXml(
517 hr = XmlGetAttributeEx(pNode, L"DisplayInternalUICondition", &pPackage->sczDisplayInternalUICondition); 518 hr = XmlGetAttributeEx(pNode, L"DisplayInternalUICondition", &pPackage->sczDisplayInternalUICondition);
518 ExitOnOptionalXmlQueryFailure(hr, fXmlFound, "Failed to get DisplayInternalUICondition setting for package."); 519 ExitOnOptionalXmlQueryFailure(hr, fXmlFound, "Failed to get DisplayInternalUICondition setting for package.");
519 520
521 hr = XmlGetAttributeEx(pNode, L"DisplayFilesInUseDialogCondition", &pPackage->sczDisplayFilesInUseDialogCondition);
522 ExitOnOptionalXmlQueryFailure(hr, fXmlFound, "Failed to get DisplayFilesInUseDialogCondition setting for package.");
523
520 hr = XmlGetAttributeEx(pNode, L"PrimaryPackageType", &scz); 524 hr = XmlGetAttributeEx(pNode, L"PrimaryPackageType", &scz);
521 ExitOnOptionalXmlQueryFailure(hr, fXmlFound, "Failed to get PrimaryPackageType setting for package."); 525 ExitOnOptionalXmlQueryFailure(hr, fXmlFound, "Failed to get PrimaryPackageType setting for package.");
522 526
diff --git a/src/api/burn/balutil/inc/balinfo.h b/src/api/burn/balutil/inc/balinfo.h
index 234284f6..8baee844 100644
--- a/src/api/burn/balutil/inc/balinfo.h
+++ b/src/api/burn/balutil/inc/balinfo.h
@@ -54,6 +54,7 @@ typedef struct _BAL_INFO_PACKAGE
54 BOOL fPermanent; 54 BOOL fPermanent;
55 BOOL fVital; 55 BOOL fVital;
56 LPWSTR sczDisplayInternalUICondition; 56 LPWSTR sczDisplayInternalUICondition;
57 LPWSTR sczDisplayFilesInUseDialogCondition;
57 LPWSTR sczProductCode; 58 LPWSTR sczProductCode;
58 LPWSTR sczUpgradeCode; 59 LPWSTR sczUpgradeCode;
59 LPWSTR sczVersion; 60 LPWSTR sczVersion;
diff --git a/src/ext/Bal/stdbas/WixStandardBootstrapperApplication.cpp b/src/ext/Bal/stdbas/WixStandardBootstrapperApplication.cpp
index 6cfe0b4c..ddb2d1c5 100644
--- a/src/ext/Bal/stdbas/WixStandardBootstrapperApplication.cpp
+++ b/src/ext/Bal/stdbas/WixStandardBootstrapperApplication.cpp
@@ -1231,34 +1231,52 @@ public: // IBootstrapperApplication
1231 __inout int* pResult 1231 __inout int* pResult
1232 ) 1232 )
1233 { 1233 {
1234 HRESULT hr = S_OK;
1235 BAL_INFO_PACKAGE* pPackage = NULL;
1236 BOOL fShowFilesInUseDialog = TRUE;
1234 1237
1235 if (!m_fShowingInternalUiThisPackage && wzPackageId && *wzPackageId) 1238 if (!m_fShowingInternalUiThisPackage && wzPackageId && *wzPackageId)
1236 { 1239 {
1237 BalLog(BOOTSTRAPPER_LOG_LEVEL_VERBOSE, "Package %ls has %d applications holding files in use.", wzPackageId, cFiles); 1240 BalLog(BOOTSTRAPPER_LOG_LEVEL_VERBOSE, "Package %ls has %d applications holding files in use.", wzPackageId, cFiles);
1238 1241
1239 switch (source) 1242 hr = BalInfoFindPackageById(&m_Bundle.packages, wzPackageId, &pPackage);
1243 if (SUCCEEDED(hr) && pPackage->sczDisplayFilesInUseDialogCondition)
1240 { 1244 {
1241 case BOOTSTRAPPER_FILES_IN_USE_TYPE_MSI: 1245 hr = BalEvaluateCondition(pPackage->sczDisplayFilesInUseDialogCondition, &fShowFilesInUseDialog);
1242 if (m_fShowStandardFilesInUse) 1246 BalExitOnFailure(hr, "Failed to evaluate condition for package '%ls': %ls", wzPackageId, pPackage->sczDisplayFilesInUseDialogCondition);
1243 { 1247 }
1244 return ShowMsiFilesInUse(cFiles, rgwzFiles, source, pResult); 1248
1245 } 1249 if (fShowFilesInUseDialog)
1246 break; 1250 {
1247 case BOOTSTRAPPER_FILES_IN_USE_TYPE_MSI_RM: 1251 switch (source)
1248 if (m_fShowRMFilesInUse)
1249 {
1250 return ShowMsiFilesInUse(cFiles, rgwzFiles, source, pResult);
1251 }
1252 break;
1253 case BOOTSTRAPPER_FILES_IN_USE_TYPE_NETFX:
1254 if (m_fShowNetfxFilesInUse)
1255 { 1252 {
1256 return ShowNetfxFilesInUse(cFiles, rgwzFiles, pResult); 1253 case BOOTSTRAPPER_FILES_IN_USE_TYPE_MSI:
1254 if (m_fShowStandardFilesInUse)
1255 {
1256 return ShowMsiFilesInUse(cFiles, rgwzFiles, source, pResult);
1257 }
1258 break;
1259 case BOOTSTRAPPER_FILES_IN_USE_TYPE_MSI_RM:
1260 if (m_fShowRMFilesInUse)
1261 {
1262 return ShowMsiFilesInUse(cFiles, rgwzFiles, source, pResult);
1263 }
1264 break;
1265 case BOOTSTRAPPER_FILES_IN_USE_TYPE_NETFX:
1266 if (m_fShowNetfxFilesInUse)
1267 {
1268 return ShowNetfxFilesInUse(cFiles, rgwzFiles, pResult);
1269 }
1270 break;
1257 } 1271 }
1258 break; 1272 }
1273 else
1274 {
1275 *pResult = IDIGNORE;
1259 } 1276 }
1260 } 1277 }
1261 1278
1279 LExit:
1262 return __super::OnExecuteFilesInUse(wzPackageId, cFiles, rgwzFiles, nRecommendation, source, pResult); 1280 return __super::OnExecuteFilesInUse(wzPackageId, cFiles, rgwzFiles, nRecommendation, source, pResult);
1263 } 1281 }
1264 1282
diff --git a/src/ext/Bal/test/WixToolsetTest.BootstrapperApplications/BalExtensionFixture.cs b/src/ext/Bal/test/WixToolsetTest.BootstrapperApplications/BalExtensionFixture.cs
index 07d3dacb..576e7c6c 100644
--- a/src/ext/Bal/test/WixToolsetTest.BootstrapperApplications/BalExtensionFixture.cs
+++ b/src/ext/Bal/test/WixToolsetTest.BootstrapperApplications/BalExtensionFixture.cs
@@ -56,6 +56,44 @@ namespace WixToolsetTest.BootstrapperApplications
56 } 56 }
57 57
58 [TestMethod] 58 [TestMethod]
59 public void CanBuildUsingDisplayFilesInUseDialogCondition()
60 {
61 using (var fs = new DisposableFileSystem())
62 {
63 var baseFolder = fs.GetFolder();
64 var bundleFile = Path.Combine(baseFolder, "bin", "test.exe");
65 var bundleSourceFolder = TestData.Get(@"TestData\WixStdBa");
66 var intermediateFolder = Path.Combine(baseFolder, "obj");
67 var baFolderPath = Path.Combine(baseFolder, "ba");
68 var extractFolderPath = Path.Combine(baseFolder, "extract");
69
70 var compileResult = WixRunner.Execute(new[]
71 {
72 "build",
73 Path.Combine(bundleSourceFolder, "DisplayFilesInUseDialogConditionBundle.wxs"),
74 "-ext", TestData.Get(@"WixToolset.BootstrapperApplications.wixext.dll"),
75 "-intermediateFolder", intermediateFolder,
76 "-bindpath", Path.Combine(bundleSourceFolder, "data"),
77 "-o", bundleFile,
78 });
79 compileResult.AssertSuccess();
80
81 Assert.IsTrue(File.Exists(bundleFile));
82
83 var extractResult = BundleExtractor.ExtractBAContainer(null, bundleFile, baFolderPath, extractFolderPath);
84 extractResult.AssertSuccess();
85
86 var balPackageInfos = extractResult.GetBADataTestXmlLines("/ba:BootstrapperApplicationData/ba:WixBalPackageInfo");
87 WixAssert.CompareLineByLine(new string[]
88 {
89 "<WixBalPackageInfo PackageId='test.msi' DisplayFilesInUseDialogCondition='1' />",
90 }, balPackageInfos);
91
92 Assert.IsTrue(File.Exists(Path.Combine(baFolderPath, "thm.wxl")));
93 }
94 }
95
96 [TestMethod]
59 public void CanBuildUsingBootstrapperApplicationId() 97 public void CanBuildUsingBootstrapperApplicationId()
60 { 98 {
61 using (var fs = new DisposableFileSystem()) 99 using (var fs = new DisposableFileSystem())
@@ -298,6 +336,7 @@ namespace WixToolsetTest.BootstrapperApplications
298 { 336 {
299 "bal:Condition/@Condition contains the built-in Variable 'WixBundleAction', which is not available when it is evaluated. (Unavailable Variables are: 'WixBundleAction'.). Rewrite the condition to avoid Variables that are never valid during its evaluation.", 337 "bal:Condition/@Condition contains the built-in Variable 'WixBundleAction', which is not available when it is evaluated. (Unavailable Variables are: 'WixBundleAction'.). Rewrite the condition to avoid Variables that are never valid during its evaluation.",
300 "Overridable variable 'TEST1' collides with 'Test1' with Bundle/@CommandLineVariables value 'caseInsensitive'.", 338 "Overridable variable 'TEST1' collides with 'Test1' with Bundle/@CommandLineVariables value 'caseInsensitive'.",
339 "The *Package/@bal:DisplayFilesInUseDialogCondition attribute's value '=' is not a valid bundle condition.",
301 "The *Package/@bal:DisplayInternalUICondition attribute's value '=' is not a valid bundle condition.", 340 "The *Package/@bal:DisplayInternalUICondition attribute's value '=' is not a valid bundle condition.",
302 "The location of the Variable related to the previous error.", 341 "The location of the Variable related to the previous error.",
303 }, messages.ToArray()); 342 }, messages.ToArray());
diff --git a/src/ext/Bal/test/WixToolsetTest.BootstrapperApplications/InternalUIBAFixture.cs b/src/ext/Bal/test/WixToolsetTest.BootstrapperApplications/InternalUIBAFixture.cs
index 72e31540..7b4d00fc 100644
--- a/src/ext/Bal/test/WixToolsetTest.BootstrapperApplications/InternalUIBAFixture.cs
+++ b/src/ext/Bal/test/WixToolsetTest.BootstrapperApplications/InternalUIBAFixture.cs
@@ -168,6 +168,7 @@ namespace WixToolsetTest.BootstrapperApplications
168 "WixInternalUIBootstrapperApplication does not support the value of 'force' for Cache on prereq packages. Prereq packages are only cached when they need to be installed.", 168 "WixInternalUIBootstrapperApplication does not support the value of 'force' for Cache on prereq packages. Prereq packages are only cached when they need to be installed.",
169 "WixInternalUIBootstrapperApplication ignores InstallCondition for the primary package so that the MSI UI is always shown.", 169 "WixInternalUIBootstrapperApplication ignores InstallCondition for the primary package so that the MSI UI is always shown.",
170 "WixInternalUIBootstrapperApplication ignores DisplayInternalUICondition for the primary package so that the MSI UI is always shown.", 170 "WixInternalUIBootstrapperApplication ignores DisplayInternalUICondition for the primary package so that the MSI UI is always shown.",
171 "WixInternalUIBootstrapperApplication ignores DisplayFilesInUseDialogCondition for the primary package so that the MSI UI is always shown.",
171 "When using WixInternalUIBootstrapperApplication, all prereq packages should be before the primary package in the chain. The prereq packages are always installed before the primary package.", 172 "When using WixInternalUIBootstrapperApplication, all prereq packages should be before the primary package in the chain. The prereq packages are always installed before the primary package.",
172 }, compileResult.Messages.Select(m => m.ToString()).ToArray()); 173 }, compileResult.Messages.Select(m => m.ToString()).ToArray());
173 174
@@ -181,7 +182,7 @@ namespace WixToolsetTest.BootstrapperApplications
181 var balPackageInfos = extractResult.GetBADataTestXmlLines("/ba:BootstrapperApplicationData/ba:WixBalPackageInfo"); 182 var balPackageInfos = extractResult.GetBADataTestXmlLines("/ba:BootstrapperApplicationData/ba:WixBalPackageInfo");
182 WixAssert.CompareLineByLine(new string[] 183 WixAssert.CompareLineByLine(new string[]
183 { 184 {
184 "<WixBalPackageInfo PackageId='test.msi' DisplayInternalUICondition='DISPLAYTEST' PrimaryPackageType='default' />", 185 "<WixBalPackageInfo PackageId='test.msi' DisplayInternalUICondition='DISPLAYTEST' DisplayFilesInUseDialogCondition='DISPLAYTEST' PrimaryPackageType='default' />",
185 }, balPackageInfos); 186 }, balPackageInfos);
186 187
187 var mbaPrereqInfos = extractResult.GetBADataTestXmlLines("/ba:BootstrapperApplicationData/ba:WixPrereqInformation"); 188 var mbaPrereqInfos = extractResult.GetBADataTestXmlLines("/ba:BootstrapperApplicationData/ba:WixPrereqInformation");
diff --git a/src/ext/Bal/test/WixToolsetTest.BootstrapperApplications/TestData/Overridable/WrongCaseBundle.wxs b/src/ext/Bal/test/WixToolsetTest.BootstrapperApplications/TestData/Overridable/WrongCaseBundle.wxs
index 67dfc589..33b2d64c 100644
--- a/src/ext/Bal/test/WixToolsetTest.BootstrapperApplications/TestData/Overridable/WrongCaseBundle.wxs
+++ b/src/ext/Bal/test/WixToolsetTest.BootstrapperApplications/TestData/Overridable/WrongCaseBundle.wxs
@@ -9,7 +9,7 @@
9 <Variable Name="TEST1" bal:Overridable="yes" /> 9 <Variable Name="TEST1" bal:Overridable="yes" />
10 <Chain> 10 <Chain>
11 <ExePackage Permanent="yes" DetectCondition="none" SourceFile="runtimes\win-x86\native\wixnative.exe" /> 11 <ExePackage Permanent="yes" DetectCondition="none" SourceFile="runtimes\win-x86\native\wixnative.exe" />
12 <MsiPackage SourceFile="test.msi" bal:DisplayInternalUICondition="!(loc.NonsensePlanCondition)" /> 12 <MsiPackage SourceFile="test.msi" bal:DisplayInternalUICondition="!(loc.NonsensePlanCondition)" bal:DisplayFilesInUseDialogCondition="!(loc.NonsensePlanCondition)" />
13 </Chain> 13 </Chain>
14 <bal:Condition Condition="!(loc.NonsenseDetectCondition)" Message="Unsupported" /> 14 <bal:Condition Condition="!(loc.NonsenseDetectCondition)" Message="Unsupported" />
15 </Bundle> 15 </Bundle>
diff --git a/src/ext/Bal/test/WixToolsetTest.BootstrapperApplications/TestData/WixIuiBa/IuibaWarnings.wxs b/src/ext/Bal/test/WixToolsetTest.BootstrapperApplications/TestData/WixIuiBa/IuibaWarnings.wxs
index 2cf9787d..9c9aa0f8 100644
--- a/src/ext/Bal/test/WixToolsetTest.BootstrapperApplications/TestData/WixIuiBa/IuibaWarnings.wxs
+++ b/src/ext/Bal/test/WixToolsetTest.BootstrapperApplications/TestData/WixIuiBa/IuibaWarnings.wxs
@@ -6,7 +6,7 @@
6 <bal:WixInternalUIBootstrapperApplication /> 6 <bal:WixInternalUIBootstrapperApplication />
7 </BootstrapperApplication> 7 </BootstrapperApplication>
8 <Chain> 8 <Chain>
9 <MsiPackage SourceFile="test.msi" InstallCondition="INSTALLTEST" bal:DisplayInternalUICondition="DISPLAYTEST" /> 9 <MsiPackage SourceFile="test.msi" InstallCondition="INSTALLTEST" bal:DisplayInternalUICondition="DISPLAYTEST" bal:DisplayFilesInUseDialogCondition="DISPLAYTEST" />
10 <ExePackage Permanent="yes" DetectCondition="none" SourceFile="runtimes\win-x86\native\wixnative.exe" Cache="force" /> 10 <ExePackage Permanent="yes" DetectCondition="none" SourceFile="runtimes\win-x86\native\wixnative.exe" Cache="force" />
11 </Chain> 11 </Chain>
12 </Bundle> 12 </Bundle>
diff --git a/src/ext/Bal/test/WixToolsetTest.BootstrapperApplications/TestData/WixStdBa/DisplayFilesInUseDialogConditionBundle.wxs b/src/ext/Bal/test/WixToolsetTest.BootstrapperApplications/TestData/WixStdBa/DisplayFilesInUseDialogConditionBundle.wxs
new file mode 100644
index 00000000..1041eb39
--- /dev/null
+++ b/src/ext/Bal/test/WixToolsetTest.BootstrapperApplications/TestData/WixStdBa/DisplayFilesInUseDialogConditionBundle.wxs
@@ -0,0 +1,12 @@
1<?xml version="1.0" encoding="utf-8"?>
2<Wix xmlns="http://wixtoolset.org/schemas/v4/wxs"
3 xmlns:bal="http://wixtoolset.org/schemas/v4/wxs/bal">
4 <Bundle Name="WixStdBa" Version="1.0.0.0" Manufacturer="Example Corporation" UpgradeCode="75D5D534-E177-4689-AAE9-CAC1C39002C2">
5 <BootstrapperApplication>
6 <bal:WixStandardBootstrapperApplication LicenseUrl="http://wixtoolset.org/about/license/" Theme="hyperlinkLicense" />
7 </BootstrapperApplication>
8 <Chain>
9 <MsiPackage SourceFile="test.msi" bal:DisplayFilesInUseDialogCondition="1" />
10 </Chain>
11 </Bundle>
12</Wix>
diff --git a/src/ext/Bal/wixext/BalBurnBackendExtension.cs b/src/ext/Bal/wixext/BalBurnBackendExtension.cs
index 82195549..5831bb8a 100644
--- a/src/ext/Bal/wixext/BalBurnBackendExtension.cs
+++ b/src/ext/Bal/wixext/BalBurnBackendExtension.cs
@@ -51,6 +51,11 @@ namespace WixToolset.BootstrapperApplications
51 writer.WriteAttributeString("DisplayInternalUICondition", balPackageInfoSymbol.DisplayInternalUICondition); 51 writer.WriteAttributeString("DisplayInternalUICondition", balPackageInfoSymbol.DisplayInternalUICondition);
52 } 52 }
53 53
54 if (balPackageInfoSymbol.DisplayFilesInUseDialogCondition != null)
55 {
56 writer.WriteAttributeString("DisplayFilesInUseDialogCondition", balPackageInfoSymbol.DisplayFilesInUseDialogCondition);
57 }
58
54 if (balPackageInfoSymbol.PrimaryPackageType != BalPrimaryPackageType.None) 59 if (balPackageInfoSymbol.PrimaryPackageType != BalPrimaryPackageType.None)
55 { 60 {
56 writer.WriteAttributeString("PrimaryPackageType", balPackageInfoSymbol.PrimaryPackageType.ToString().ToLower()); 61 writer.WriteAttributeString("PrimaryPackageType", balPackageInfoSymbol.PrimaryPackageType.ToString().ToLower());
@@ -104,6 +109,7 @@ namespace WixToolset.BootstrapperApplications
104 109
105 this.VerifyBalConditions(section); 110 this.VerifyBalConditions(section);
106 this.VerifyDisplayInternalUICondition(section); 111 this.VerifyDisplayInternalUICondition(section);
112 this.VerifyDisplayFilesInUseDialogCondition(section);
107 this.VerifyOverridableVariables(section); 113 this.VerifyOverridableVariables(section);
108 114
109 var balBaSymbol = section.Symbols.OfType<WixBalBootstrapperApplicationSymbol>().SingleOrDefault(); 115 var balBaSymbol = section.Symbols.OfType<WixBalBootstrapperApplicationSymbol>().SingleOrDefault();
@@ -195,6 +201,17 @@ namespace WixToolset.BootstrapperApplications
195 } 201 }
196 } 202 }
197 203
204 private void VerifyDisplayFilesInUseDialogCondition(IntermediateSection section)
205 {
206 foreach (var balPackageInfoSymbol in section.Symbols.OfType<WixBalPackageInfoSymbol>().ToList())
207 {
208 if (balPackageInfoSymbol.DisplayFilesInUseDialogCondition != null)
209 {
210 this.BackendHelper.ValidateBundleCondition(balPackageInfoSymbol.SourceLineNumbers, "*Package", "bal:DisplayFilesInUseDialogCondition", balPackageInfoSymbol.DisplayFilesInUseDialogCondition, BundleConditionPhase.Plan);
211 }
212 }
213 }
214
198 private void VerifyPrimaryPackages(IntermediateSection section, SourceLineNumber baSourceLineNumbers) 215 private void VerifyPrimaryPackages(IntermediateSection section, SourceLineNumber baSourceLineNumbers)
199 { 216 {
200 WixBalPackageInfoSymbol defaultPrimaryPackage = null; 217 WixBalPackageInfoSymbol defaultPrimaryPackage = null;
@@ -420,6 +437,11 @@ namespace WixToolset.BootstrapperApplications
420 { 437 {
421 this.Messaging.Write(BalWarnings.IuibaPrimaryPackageDisplayInternalUICondition(packageSymbol.SourceLineNumbers)); 438 this.Messaging.Write(BalWarnings.IuibaPrimaryPackageDisplayInternalUICondition(packageSymbol.SourceLineNumbers));
422 } 439 }
440
441 if (balPackageInfoSymbol.DisplayFilesInUseDialogCondition != null)
442 {
443 this.Messaging.Write(BalWarnings.IuibaPrimaryPackageDisplayFilesInUseDialogCondition(packageSymbol.SourceLineNumbers));
444 }
423 } 445 }
424 446
425 private void VerifyOverridableVariables(IntermediateSection section) 447 private void VerifyOverridableVariables(IntermediateSection section)
diff --git a/src/ext/Bal/wixext/BalCompiler.cs b/src/ext/Bal/wixext/BalCompiler.cs
index 35c86233..b7d5f679 100644
--- a/src/ext/Bal/wixext/BalCompiler.cs
+++ b/src/ext/Bal/wixext/BalCompiler.cs
@@ -200,6 +200,20 @@ namespace WixToolset.BootstrapperApplications
200 break; 200 break;
201 } 201 }
202 break; 202 break;
203 case "DisplayFilesInUseDialogCondition":
204 switch (parentElement.Name.LocalName)
205 {
206 case "MsiPackage":
207 case "MspPackage":
208 var displayFilesInUseDialogCondition = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attribute);
209 var packageInfo = this.GetBalPackageInfoSymbol(section, sourceLineNumbers, packageId);
210 packageInfo.DisplayFilesInUseDialogCondition = displayFilesInUseDialogCondition;
211 break;
212 default:
213 this.ParseHelper.UnexpectedAttribute(parentElement, attribute);
214 break;
215 }
216 break;
203 case "PrimaryPackageType": 217 case "PrimaryPackageType":
204 { 218 {
205 var primaryPackageType = BalPrimaryPackageType.None; 219 var primaryPackageType = BalPrimaryPackageType.None;
diff --git a/src/ext/Bal/wixext/BalWarnings.cs b/src/ext/Bal/wixext/BalWarnings.cs
index 8c5d892f..f86837f9 100644
--- a/src/ext/Bal/wixext/BalWarnings.cs
+++ b/src/ext/Bal/wixext/BalWarnings.cs
@@ -23,6 +23,11 @@ namespace WixToolset.BootstrapperApplications
23 return Message(sourceLineNumbers, Ids.IuibaPrimaryPackageDisplayInternalUICondition, "WixInternalUIBootstrapperApplication ignores DisplayInternalUICondition for the primary package so that the MSI UI is always shown."); 23 return Message(sourceLineNumbers, Ids.IuibaPrimaryPackageDisplayInternalUICondition, "WixInternalUIBootstrapperApplication ignores DisplayInternalUICondition for the primary package so that the MSI UI is always shown.");
24 } 24 }
25 25
26 public static Message IuibaPrimaryPackageDisplayFilesInUseDialogCondition(SourceLineNumber sourceLineNumbers)
27 {
28 return Message(sourceLineNumbers, Ids.IuibaPrimaryPackageDisplayFilesInUseDialogCondition, "WixInternalUIBootstrapperApplication ignores DisplayFilesInUseDialogCondition for the primary package so that the MSI UI is always shown.");
29 }
30
26 public static Message IuibaPrimaryPackageInstallCondition(SourceLineNumber sourceLineNumbers) 31 public static Message IuibaPrimaryPackageInstallCondition(SourceLineNumber sourceLineNumbers)
27 { 32 {
28 return Message(sourceLineNumbers, Ids.IuibaPrimaryPackageInstallCondition, "WixInternalUIBootstrapperApplication ignores InstallCondition for the primary package so that the MSI UI is always shown."); 33 return Message(sourceLineNumbers, Ids.IuibaPrimaryPackageInstallCondition, "WixInternalUIBootstrapperApplication ignores InstallCondition for the primary package so that the MSI UI is always shown.");
@@ -56,6 +61,7 @@ namespace WixToolset.BootstrapperApplications
56 IuibaPrimaryPackageDisplayInternalUICondition = 6504, 61 IuibaPrimaryPackageDisplayInternalUICondition = 6504,
57 IuibaPrereqPackageAfterPrimaryPackage = 6505, 62 IuibaPrereqPackageAfterPrimaryPackage = 6505,
58 DeprecatedBAFactoryAssemblyAttribute = 6506, 63 DeprecatedBAFactoryAssemblyAttribute = 6506,
64 IuibaPrimaryPackageDisplayFilesInUseDialogCondition = 6507,
59 } 65 }
60 } 66 }
61} 67}
diff --git a/src/ext/Bal/wixext/Symbols/WixBalPackageInfoSymbol.cs b/src/ext/Bal/wixext/Symbols/WixBalPackageInfoSymbol.cs
index e2636d33..79773566 100644
--- a/src/ext/Bal/wixext/Symbols/WixBalPackageInfoSymbol.cs
+++ b/src/ext/Bal/wixext/Symbols/WixBalPackageInfoSymbol.cs
@@ -13,6 +13,7 @@ namespace WixToolset.BootstrapperApplications
13 { 13 {
14 new IntermediateFieldDefinition(nameof(WixBalPackageInfoSymbolFields.PackageId), IntermediateFieldType.String), 14 new IntermediateFieldDefinition(nameof(WixBalPackageInfoSymbolFields.PackageId), IntermediateFieldType.String),
15 new IntermediateFieldDefinition(nameof(WixBalPackageInfoSymbolFields.DisplayInternalUICondition), IntermediateFieldType.String), 15 new IntermediateFieldDefinition(nameof(WixBalPackageInfoSymbolFields.DisplayInternalUICondition), IntermediateFieldType.String),
16 new IntermediateFieldDefinition(nameof(WixBalPackageInfoSymbolFields.DisplayFilesInUseDialogCondition), IntermediateFieldType.String),
16 new IntermediateFieldDefinition(nameof(WixBalPackageInfoSymbolFields.PrimaryPackageType), IntermediateFieldType.Number), 17 new IntermediateFieldDefinition(nameof(WixBalPackageInfoSymbolFields.PrimaryPackageType), IntermediateFieldType.Number),
17 }, 18 },
18 typeof(WixBalPackageInfoSymbol)); 19 typeof(WixBalPackageInfoSymbol));
@@ -28,6 +29,7 @@ namespace WixToolset.BootstrapperApplications.Symbols
28 PackageId, 29 PackageId,
29 DisplayInternalUICondition, 30 DisplayInternalUICondition,
30 PrimaryPackageType, 31 PrimaryPackageType,
32 DisplayFilesInUseDialogCondition,
31 } 33 }
32 34
33 public enum BalPrimaryPackageType 35 public enum BalPrimaryPackageType
@@ -63,6 +65,12 @@ namespace WixToolset.BootstrapperApplications.Symbols
63 set => this.Set((int)WixBalPackageInfoSymbolFields.DisplayInternalUICondition, value); 65 set => this.Set((int)WixBalPackageInfoSymbolFields.DisplayInternalUICondition, value);
64 } 66 }
65 67
68 public string DisplayFilesInUseDialogCondition
69 {
70 get => this.Fields[(int)WixBalPackageInfoSymbolFields.DisplayFilesInUseDialogCondition].AsString();
71 set => this.Set((int)WixBalPackageInfoSymbolFields.DisplayFilesInUseDialogCondition, value);
72 }
73
66 public BalPrimaryPackageType PrimaryPackageType 74 public BalPrimaryPackageType PrimaryPackageType
67 { 75 {
68 get => (BalPrimaryPackageType)this.Fields[(int)WixBalPackageInfoSymbolFields.PrimaryPackageType].AsNumber(); 76 get => (BalPrimaryPackageType)this.Fields[(int)WixBalPackageInfoSymbolFields.PrimaryPackageType].AsNumber();
diff --git a/src/xsd/bal.xsd b/src/xsd/bal.xsd
index ff4142ad..c7bd10fa 100644
--- a/src/xsd/bal.xsd
+++ b/src/xsd/bal.xsd
@@ -623,6 +623,21 @@
623 </xs:simpleType> 623 </xs:simpleType>
624 </xs:attribute> 624 </xs:attribute>
625 625
626 <xs:attribute name="DisplayFilesInUseDialogCondition" type="xs:string">
627 <xs:annotation>
628 <xs:documentation>
629 Specifies whether the bundle will allow the Files In Use dialog to be displayed for the MSI or MSP package. If not
630 specified or the condition evaluates to true, the Files In Use dialog will be prompt the user during full UI to
631 close applications to release the file. Otherwise, the dialog will not be displayed and the package will likely
632 require a restart when files are in use.
633 </xs:documentation>
634 <xs:appinfo>
635 <xse:parent namespace="http://wixtoolset.org/schemas/v4/wxs" ref="MsiPackage" />
636 <xse:parent namespace="http://wixtoolset.org/schemas/v4/wxs" ref="MspPackage" />
637 </xs:appinfo>
638 </xs:annotation>
639 </xs:attribute>
640
626 <xs:attribute name="DisplayInternalUICondition" type="xs:string"> 641 <xs:attribute name="DisplayInternalUICondition" type="xs:string">
627 <xs:annotation> 642 <xs:annotation>
628 <xs:documentation> 643 <xs:documentation>