diff --git a/Source/src/WixSharp.Samples/Support/testpad/setup.cs b/Source/src/WixSharp.Samples/Support/testpad/setup.cs index bdebac65..c822e480 100644 --- a/Source/src/WixSharp.Samples/Support/testpad/setup.cs +++ b/Source/src/WixSharp.Samples/Support/testpad/setup.cs @@ -54,6 +54,7 @@ static void Issue_298() GUID = new Guid("6fe30b47-2577-43ad-9095-1861ba25889b") }; + project.AddRegValue(new RegValue(RegistryHive.LocalMachine, @"Software\test", "foo_value", "bar") { Win64 = true }); project.AddRegValue(new RegValue(RegistryHive.LocalMachine, @"Software\test", "foo_value", "bar") { Win64 = false }); // Compiler.LightOptions += " -sice:ICE80"; diff --git a/Source/src/WixSharp.Samples/Wix# Samples/Extensions/setup.cs b/Source/src/WixSharp.Samples/Wix# Samples/Extensions/setup.cs index a6143418..6278abc9 100644 --- a/Source/src/WixSharp.Samples/Wix# Samples/Extensions/setup.cs +++ b/Source/src/WixSharp.Samples/Wix# Samples/Extensions/setup.cs @@ -76,8 +76,8 @@ public class RemoveFolderEx : WixEntity, IGenericEntity [Xml] public new string Id { - get => base.Id; - set => base.Id = value; + get { return base.Id; } + set { base.Id = value; } } /// diff --git a/Source/src/WixSharp.Samples/Wix# Samples/External_UI/Msi/MyProduct.msi b/Source/src/WixSharp.Samples/Wix# Samples/External_UI/Msi/MyProduct.msi index 6ac50a2f..ce333cf4 100644 Binary files a/Source/src/WixSharp.Samples/Wix# Samples/External_UI/Msi/MyProduct.msi and b/Source/src/WixSharp.Samples/Wix# Samples/External_UI/Msi/MyProduct.msi differ diff --git a/Source/src/WixSharp.Samples/Wix# Samples/Managed Setup/CustomUIDialog/setup.cs b/Source/src/WixSharp.Samples/Wix# Samples/Managed Setup/CustomUIDialog/setup.cs index eaa9b6b8..42d8bf49 100644 --- a/Source/src/WixSharp.Samples/Wix# Samples/Managed Setup/CustomUIDialog/setup.cs +++ b/Source/src/WixSharp.Samples/Wix# Samples/Managed Setup/CustomUIDialog/setup.cs @@ -26,8 +26,6 @@ static public void Main(string[] args) //Note if the property 'PASSWORD' is not preserved as deferred then it will not be available //from the Project_AfterInstall, which is a deferred custom action. - AutoElements.LagacyDummyDirAlgorithm = true; - var project = new ManagedProject("ManagedSetup", new User { diff --git a/Source/src/WixSharp.Samples/WixSharp.xml b/Source/src/WixSharp.Samples/WixSharp.xml index 57678935..db55e3e5 100644 --- a/Source/src/WixSharp.Samples/WixSharp.xml +++ b/Source/src/WixSharp.Samples/WixSharp.xml @@ -1375,6 +1375,19 @@ Forces all values to be always encoded as CDATA. + + + Flag indicating if the legacy algorithm should be used for handling setups with no directories + to be installed but only non-file system components (e.g. RegKey, User, Firewall exceptions). + The algorithm used in early versions of WixSharp (legacy algorithm) injects a dummy + directory into the setup definition so it satisfies the MSI constraint that every component must + belong to a directory. As many other rules this one has no practical value and rather reflection + of the outdated (~20 years ago) deployment approaches. + The current algorithm also ensures the that there is a XML directory to host the components. + However instead of custom (dummy) directory it inserts 'ProgramFilesFolder'. This way MSI constraint + is satisfied and yet there is no impact on the target file system. + + Disables automatic insertion of user profile registry elements. diff --git a/Source/src/WixSharp/AutoElements.cs b/Source/src/WixSharp/AutoElements.cs index 0adbe6c4..ac09c780 100644 --- a/Source/src/WixSharp/AutoElements.cs +++ b/Source/src/WixSharp/AutoElements.cs @@ -132,7 +132,18 @@ public static class AutoElements /// public static bool ForceCDataForConditions = false; - public static bool LagacyDummyDirAlgorithm = false; + /// + /// Flag indicating if the legacy algorithm should be used for handling setups with no directories + /// to be installed but only non-file system components (e.g. RegKey, User, Firewall exceptions). + /// The algorithm used in early versions of WixSharp (legacy algorithm) injects a dummy + /// directory into the setup definition so it satisfies the MSI constraint that every component must + /// belong to a directory. As many other rules this one has no practical value and rather reflection + /// of the outdated (~20 years ago) deployment approaches. + /// The current algorithm also ensures the that there is a XML directory to host the components. + /// However instead of custom (dummy) directory it inserts 'ProgramFilesFolder'. This way MSI constraint + /// is satisfied and yet there is no impact on the target file system. + /// + public static bool LegacyDummyDirAlgorithm = false; /// /// Disables automatic insertion of user profile registry elements. @@ -549,7 +560,7 @@ internal static void HandleEmptyDirectories(XDocument doc) //'EMPTY DIRECTORY' support processing section foreach (XElement item in componentsWithNoFiles) { - // Ridiculous MSI constrains: + // Ridiculous MSI constraints: // * you cannot install install empty folders // - workaround is to insert empty component with CreateFolder element // * if Component+CreateFolder element is inserted the folder will not be removed on uninstall diff --git a/Source/src/WixSharp/CommonTasks.cs b/Source/src/WixSharp/CommonTasks.cs index 19be607f..a4e3a69b 100644 --- a/Source/src/WixSharp/CommonTasks.cs +++ b/Source/src/WixSharp/CommonTasks.cs @@ -1285,6 +1285,20 @@ static public XElement CreateParentComponent(this WixEntity entity) return new XElement("Component").AddAttributes($@"Id={entity.Id}; Guid={WixGuid.NewGuid(entity.Id)}"); } + static public XElement FistProgramFilesDir(this XElement element) + { + XElement dir = element.FindFirst("Directory"); + while (dir != null) + { + if (dir.HasAttribute("Name", x => x.StartsWith("ProgramFiles") && x.EndsWith("Folder"))) + return dir; + + dir = dir.Elements("Directory").FirstOrDefault(); + } + + return null; + } + /// /// Installs the windows service. It uses InstallUtil.exe to complete the actual installation/uninstallation. /// During the run for the InstallUtil.exe console window is hidden. diff --git a/Source/src/WixSharp/Compiler.cs b/Source/src/WixSharp/Compiler.cs index 7c919d91..48d3813c 100644 --- a/Source/src/WixSharp/Compiler.cs +++ b/Source/src/WixSharp/Compiler.cs @@ -1406,7 +1406,7 @@ public static XDocument GenerateWixProj(Project project) if (!project.LicenceFile.IsEmpty()) { if (!AllowNonRtfLicense && !project.LicenceFile.EndsWith(".rtf", StringComparison.OrdinalIgnoreCase)) - throw new ApplicationException("License file must have 'rtf' file extension. Specify 'Compiler.AllowNonRtfLicense=true' to overcome this constrain."); + throw new ApplicationException("License file must have 'rtf' file extension. Specify 'Compiler.AllowNonRtfLicense=true' to overcome this constraint."); product.Add( new XElement("WixVariable", @@ -1450,7 +1450,7 @@ static string AutoAssignInstallDirId(Dir[] wDirs, string dirId) Compiler.OutputWriteLine($"WARNING: Special folder directory ID '{firstDirWithItems.Id}' has been reset to '{dirId}'.\n" + "If it was not intended disable auto assignment by setting 'Compiler.AutoGeneration.InstallDirDefaultId' to null.\n" + "Or set 'Dir.IsInstallDir = true' for the installation directory.\r" + - "Or use instead of 'new Dir(...' use 'new InstallDir(...' for the installation directory."); + "Or instead of 'new Dir(...' use 'new InstallDir(...' for the installation directory."); firstDirWithItems.Id = dirId; return logicalPath; @@ -1709,7 +1709,7 @@ static void ProcessDirectory(Dir wDir, Project wProject, Dictionary