Beispiel #1
0
        static void InsertEmptyComponentsInParentDirectories(XDocument doc, XElement item)
        {
            XElement parent = item.Parent("Directory");

            while (parent != null)
            {
                if (parent.Element("Component") == null)
                {
                    var dirId = parent.Attribute("Id")?.Value;
                    if (Compiler.EnvironmentConstantsMapping.ContainsValue(dirId))
                    {
                        break; //stop when reached start of user defined subdirs chain: TARGETDIR/ProgramFilesFolder!!!/ProgramFilesFolder.Company/INSTALLDIR
                    }
                    //just folder with nothing in it but not the last leaf
                    doc.CreateComponentFor(parent);
                }
                parent = parent.Parent("Directory");
            }
        }
Beispiel #2
0
        internal static void InjectAutoElementsHandler(XDocument doc, Project project)
        {
            ExpandCustomAttributes(doc, project);
            InjectShortcutIcons(doc);
            HandleEmptyDirectories(doc);

            XElement product = doc.Root.Select("Product");

            int?absPathCount = null;

            foreach (XElement dir in product.Element("Directory").Elements("Directory"))
            {
                XElement installDir = dir;

                XAttribute installDirName = installDir.Attribute("Name");
                if (IO.Path.IsPathRooted(installDirName.Value))
                {
                    string absolutePath = installDirName.Value;

                    if (dir == product.Element("Directory").Elements("Directory").First()) //only for the first root dir
                    {
                        //ManagedUI will need some hint on the install dir as it cannot rely on the session action (e.g. Set_INSTALLDIR_AbsolutePath)
                        //because it is running outside of the sequence and analyses the tables directly for the INSTALLDIR
                        product.AddElement("Property", "Id=INSTALLDIR_ABSOLUTEPATH; Value=" + absolutePath);
                    }

                    installDirName.Value = $"ABSOLUTEPATH{absPathCount}";

                    //<SetProperty> for INSTALLDIR is an attractive approach but it doesn't allow conditional setting of 'ui' and 'execute' as required depending on UI level
                    // it is ether hard-coded 'both' or hard coded-both 'ui' or 'execute'
                    // <SetProperty Id="INSTALLDIR" Value="C:\My Company\MyProduct" Sequence="both" Before="AppSearch">

                    string actualDirName = installDir.Attribute("Id").Value;
                    string customAction  = $"Set_DirAbsolutePath{absPathCount}";

                    product.Add(new XElement("CustomAction",
                                             new XAttribute("Id", customAction),
                                             new XAttribute("Property", actualDirName),
                                             new XAttribute("Value", absolutePath)));

                    product.SelectOrCreate("InstallExecuteSequence").Add(
                        new XElement("Custom", $"(NOT Installed) AND (UILevel < 5) AND ({actualDirName} = ABSOLUTEPATH{absPathCount})",
                                     new XAttribute("Action", customAction),
                                     new XAttribute("Before", "AppSearch")));

                    product.SelectOrCreate("InstallUISequence").Add(
                        new XElement("Custom", $"(NOT Installed) AND (UILevel = 5) AND ({actualDirName} = ABSOLUTEPATH{absPathCount})",
                                     new XAttribute("Action", customAction),
                                     new XAttribute("Before", "AppSearch")));

                    if (absPathCount == null)
                    {
                        absPathCount = 0;
                    }
                    absPathCount++;
                }
            }

            CreateEmptyComponentsInDirectoriesToRemove(doc);

            foreach (XElement xDir in product.Descendants("Directory").ToArray())
            {
                var dirComponents = xDir.Elements("Component").ToArray();

                if (dirComponents.Any())
                {
                    var componentsWithNoFilesOrRegistry = dirComponents.Where(x => !x.ContainsFilesOrRegistries()).ToArray();

                    foreach (XElement item in componentsWithNoFilesOrRegistry)
                    {
                        //if (!item.Attribute("Id").Value.EndsWith(".EmptyDirectory"))
                        EnsureKeyPath(item);

                        if (!xDir.ContainsAnyRemoveFolder())
                        {
                            InsertRemoveFolder(xDir, item, "uninstall"); //to keep WiX/compiler happy and allow removal of the dummy directory
                        }
                    }
                }

                foreach (XElement xComp in dirComponents)
                {
                    if (xDir.InUserProfile())
                    {
                        if (!xDir.ContainsAnyRemoveFolder())
                        {
                            InsertRemoveFolder(xDir, xComp);
                        }

                        if (!xComp.ContainsDummyUserProfileRegistry())
                        {
                            InsertDummyUserProfileRegistry(xComp);
                        }
                    }
                    else
                    {
                        if (xComp.ContainsNonAdvertisedShortcuts())
                        {
                            if (!xComp.ContainsDummyUserProfileRegistry())
                            {
                                InsertDummyUserProfileRegistry(xComp);
                            }
                        }
                    }

                    foreach (XElement xFile in xComp.Elements("File"))
                    {
                        if (xFile.ContainsAdvertisedShortcuts() && !xComp.ContainsDummyUserProfileRegistry())
                        {
                            SetFileKeyPath(xFile);
                        }
                    }
                }

                if (!xDir.ContainsComponents() && xDir.InUserProfile())
                {
                    if (!xDir.IsUserProfileRoot())
                    {
                        XElement xComp1 = doc.CreateComponentFor(xDir);
                        if (!xDir.ContainsAnyRemoveFolder())
                        {
                            InsertRemoveFolder(xDir, xComp1);
                        }

                        if (!xComp1.ContainsDummyUserProfileRegistry())
                        {
                            InsertDummyUserProfileRegistry(xComp1);
                        }
                    }
                }
            }

            //Not a property Id as MSI requires
            Predicate <string> needsProperty =
                value => value.Contains("\\") ||
                value.Contains("//") ||
                value.Contains("%") ||
                value.Contains("[") ||
                value.Contains("]");

            foreach (XElement xShortcut in product.Descendants("Shortcut"))
            {
                if (xShortcut.HasAttribute("WorkingDirectory", x => needsProperty(x)))
                {
                    string workingDirectory = xShortcut.Attribute("WorkingDirectory").Value;

                    if (workingDirectory.StartsWith("%") && workingDirectory.EndsWith("%")) //%INSTALLDIR%
                    {
                        workingDirectory = workingDirectory.ExpandWixEnvConsts();
                        xShortcut.SetAttributeValue("WorkingDirectory", workingDirectory.Replace("%", ""));
                    }
                    else if (workingDirectory.StartsWith("[") && workingDirectory.EndsWith("]")) //[INSTALLDIR]
                    {
                        xShortcut.SetAttributeValue("WorkingDirectory", workingDirectory.Replace("[", "").Replace("]", ""));
                    }
                    else
                    {
                        string   workinDirPath    = workingDirectory.ReplaceWixSharpEnvConsts();
                        XElement existingProperty = product.Descendants("Property")
                                                    .FirstOrDefault(p => p.HasAttribute("Value", workingDirectory));

                        if (existingProperty != null)
                        {
                            xShortcut.SetAttributeValue("WorkingDirectory", existingProperty.Attribute("Id").Value);
                        }
                        else
                        {
                            string propId = xShortcut.Attribute("Id").Value + ".WorkDir";
                            product.AddElement("Property", "Id=" + propId + "; Value=" + workinDirPath);
                            xShortcut.SetAttributeValue("WorkingDirectory", propId);
                        }
                    }
                }
            }

            InjectPlatformAttributes(doc);
        }