В Wix# как избежать создания физической папки в целевой системе при развертывании только записей реестра?

У меня есть несколько связанных записей реестра Windows, которые я хочу упаковать в MSI, так что 1) происходит процесс удаления, и 2) тот факт, что эти записи реестра были применены к данному компьютеру, задокументирован записью "Установка и удаление программ".,

Проблема в том, что я могу заставить Wix# сделать это просто отлично, но я могу заставить MSI собирать только если все записи реестра находятся внутри блока "Dir", и это фактически приводит к созданию физической папки, которую я надеваю не хочу, на целевой системе.

В качестве временного решения я обернулся с помощью блока Dir, указав фиктивную папку "Temp". Инсталлятор фактически создает папку, которую я не хочу; все, что я хочу - это применить записи реестра.

В документации WiX описывается его базовая конструкция, TargetDir, как по существу указание установщику выполнить свои действия в целевой системе. См. http://wixtoolset.org/documentation/manual/v3/howtos/files_and_registry/write_a_registry_entry.html

В этом родном примере WiX XML кажется, что в целевой системе не будет создано никаких посторонних папок; будут применяться только нужные записи реестра. Какую синтаксическую конструкцию Wix# можно использовать для применения записей реестра, но при этом не нужно создавать фактическую папку в целевой системе?

Кажется, что все примеры Wix#, которые я видел до сих пор, имеют такой побочный эффект, как создание реальной папки в целевой системе, хотите ли вы одну или нет.

Я знаю, что, вероятно, мог бы сделать это, взяв.reg файлы записей реестра, собрав их в файлы.wxs с высокой температурой, а затем собрав их в msi со свечой и светом. Я действительно пытаюсь сохранить это в мире C#/Wix#. C# - это хорошо понятный набор навыков в моей организации; WiX меньше так. (Признание того, что Wix# построен на основе функций WiX, и некоторая степень понимания WiX и установщика Windows является существенной; это удобная зона, возможность использовать C# вместо XML, а не полностью логичная вещь.) В настоящее время мы выполняем многие из этих типов задач настройки реестра вручную, без каких-либо следов и без простой и надежной деинсталляции.

/// <summary>
/// Configure the Event Log on a Windows (server) to have MyApplication Log settings and record an entry for it in Programs and Features.
/// Note that this program creates the Windows Installer MSI that accomplishes this.  
/// This program creates a WiX XML file that is then compiled by the WiX Toolkit (Candle and Light) into the MSI file.
/// </summary>
internal class Script
{
    public static void Main()
    {
        // Define a new Installer Project object
        var project = new Project("SetupMyApplicationEventLog" ,
        // Provide dummy "Temp" install directory to satisfy WiX# Syntactical requirement. There are no actual files being installed.
        new Dir(@"Temp"),
            /*
                * Event Log Registration Entries, translated from .reg file
            */
            // First, add the root level key of the tree of keys

            //[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Eventlog\MyApplication Log]
            //"EventMessageFile"="C:\\Windows\\Microsoft.NET\\Framework64\\v2.0.50727\\EventLogMessages.dll"
            new RegValue(
                RegistryHive.LocalMachine,
                @"SYSTEM\CurrentControlSet\Services\Eventlog\MyApplication Log",
                "",
                "") { AttributesDefinition = "Component:Win64=yes" },

            //[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Eventlog\MyApplication Log\STV.DSD.HQSYS.SERVICE2]
            //"EventMessageFile"="C:\\Windows\\Microsoft.NET\\Framework64\\v2.0.50727\\EventLogMessages.dll"
            new RegValue(
                RegistryHive.LocalMachine,
                @"SYSTEM\CurrentControlSet\Services\Eventlog\MyApplication Log\" + "STV.DSD.HQSYS.SERVICE2",
                "EventMessageFile",
                "C:\\Windows\\Microsoft.NET\\Framework64\\v2.0.50727\\EventLogMessages.dll") { AttributesDefinition = "Component:Win64=yes" },

            //[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Eventlog\MyApplication Log\STV.VFS.ONLINE]
            //"EventMessageFile"="C:\\Windows\\Microsoft.NET\\Framework64\\v2.0.50727\\EventLogMessages.dll"
            new RegValue(
                RegistryHive.LocalMachine,
                @"SYSTEM\CurrentControlSet\Services\Eventlog\MyApplication Log\" + "STV.VFS.ONLINE",
                "EventMessageFile",
                "C:\\Windows\\Microsoft.NET\\Framework64\\v2.0.50727\\EventLogMessages.dll") { AttributesDefinition = "Component:Win64=yes" } );

        // Set the properties of the setup project

        // Set UI to minimal; there are no choices to be made here.
        project.UI = WUI.WixUI_ProgressOnly;
        project.Manufacturer = "STV";
        project.OutFileName = "SetupMyApplicationEventLog";
        project.GUID = new Guid("037C625A-609C-4C2C-9689-62A075B88AD7");
        // Assign version # to setup MSI property of type System.Version 
        project.Version = new Version(4, 0, 0, 0);

        // Add the Win64 attribute to the package, to force a 64-bit MSI to be created
        project.Package.AttributesDefinition = "Platform=x64";

        // Trigger the MSI file build
        Compiler.BuildMsi(project);

        //// Also create the .wxs file so we can see what was sent to WiX to build the MSI
        Compiler.BuildWxs(project);

        Console.WriteLine("productVersion=" + project.Version);
        Console.ReadLine();
    }
}

}

2 ответа

Решение

Вы можете достичь того, что вы хотите, добавив <RemoveFolder> пометьте свой компонент в каталоге, который вы не хотите хранить. Смотрите ссылку.

Полученный MSI будет создан light с предупреждением LGHT1079 что у вас нет файлов, но их можно игнорировать, если это так.

Простой пример XML, показывающий каталог с компонентом, который удаляет папку при установке / удалении и создает ключи реестра, заставляя удалить при удалении.

<Directory Id="TARGETDIR" Name="SourceDir">
    <Component Id="ApplicationRegistry" Guid="YOUR-GUID-HERE">
         <RemoveFolder Id="RemoveTarget" Directory="TARGETDIR" On="both"/> 
         <RegistryKey Root="HKCU"
              Key="Software\Microsoft\[ProductName]"
              ForceDeleteOnUninstall="yes">
                <RegistryValue Type="integer" Name="SomeIntegerValue" Value="1" KeyPath="yes"/>
                <RegistryValue Type="string" Value="Default Value"/>
         </RegistryKey>
    </Component>
</Directory>

Вы бы просто использовали это имя для своего каталога или заменили Directory="TARGETDIR" с названием вашего каталога.

Результатом после установки является раздел реестра без папки на целевом компьютере.ключ реестрадорожка

Вы должны выяснить, как вставить этот тег в ваш сгенерированный XML, но это тот эффект, который вам нужен.

Используя код Wix XML, предоставленный Райаном Дж, плюс пример "InjectXML" из кода примеров Wix#, я успешно создал файл wxs и получил работающий MSI, все еще оставаясь в среде кодирования Wix# в Visual Studio.

Вот соответствующий XML.wxs, который был сгенерирован ранее, под элементом:

<Directory Id="TARGETDIR" Name="SourceDir" >
  <Directory Id="INSTALLDIR" Name="%Temp%">
    <Component Id="INSTALLDIR.EmptyDirectory" Guid="037c625a-609c-4c2c-9689-62a075b88ae9">
      <CreateFolder />
    </Component>

Итак, что должно произойти: 1) Удалите элемент "", который находится в Product/Directory/Directory/Component. Пример Райана Дж ясно показал, что он относится к "Компоненту", связанному с первым "Каталогом", который должен быть создан, что в свою очередь относится к "TARGETDIR" в XML, который генерирует Wix#.

2) Вставьте синтаксис элемента "" под элементом Product/Directory/Directory/Component. Хотя я полагаю, что в этом элементе также можно ссылаться на идентификатор "INSTALLDIR.EmptyDirectory", я использовал идентификатор "TARGETDIR", и он работал так, как я хотел.

Вот результирующий код Wix#, который внедряет XML, предоставленный Райаном Дж.

    internal class Script
    {
        public static void Main()
        {
            // Define a new Installer Project object
            var project = new Project("SetupMyApplicationEventLog" ,
            // Provide dummy "Temp" install directory to satisfy WiX# Syntactical requirement. There are no actual files being installed.
            new Dir(@"TempDeleteMe"),
...
            // Hook up a delegate to the "WixSourceGenerated" event, fires when .wxs file is fully created
            Compiler.WixSourceGenerated += InjectXMLElement;
            // Trigger the MSI file build
            Compiler.BuildMsi(project);
...

        /// Insert XML elements and attributes into the generated .wxs file
        static void InjectXMLElement(System.Xml.Linq.XDocument document)
        {
            // Remove the <CreateFolder /> tag from Directory element -- we don't want to create it
            var createFolderElement = document.Root.Select("Product/Directory/Directory/Component/CreateFolder");
            createFolderElement.Remove();
            // To cause the folder to not be created on the target system, add this element:
            // <RemoveFolder Id="RemoveTarget" Directory="TARGETDIR" On="both"/>
            var componentElement = document.Root.Select("Product/Directory/Directory/Component");
            
            componentElement.Add(new XElement("RemoveFolder",
                       new XAttribute("Id", "RemoveTarget"),
                       new XAttribute("Directory", "TARGETDIR"),
                       new XAttribute("On","both")));
        }

Другие вопросы по тегам