In Wix #, how to avoid creating a physical folder on the target system when deploying only registry entries?

I have several related Windows registry entries that I want to package inside MSI, so 1) there is a deletion process and 2) The fact that these registry entries were applied to this computer is documented using Add / Remove Programs.

The problem is that I can get Wix # to do it just fine, but I can only get MSI for assembly if all the registry entries are inside the Dir block, and this leads to the creation of a physical folder that I don't want on the target system.

As a temporary workaround, I ended up using Dir block by specifying a Temp layout folder. The installer does create a folder that I do not want; all i want is to use registry entries.

The WiX documentation describes its basic design, TargetDir, which essentially tells the installer to complete its actions on the target system. See http://wixtoolset.org/documentation/manual/v3/howtos/files_and_registry/write_a_registry_entry.html

In this native WiX XML example, it seems that there will be no extraneous folder on the target system; only the necessary entries in the registry will be applied. What Wix # syntax construct can be used to apply registry entries, but don't need to create the actual folder on the target system?

All the Wix # samples I've seen so far seem to have this side effect of creating the actual folder on the target system, whether you want it or not.

I know that perhaps I could do this by taking REG files from registry entries, compiling them into high temperature .wxs files, and then building them for msi with a candle and light. I am really trying to keep this in a C # / Wix # world. C # is a well-understood set of skills in my organization; WiX less. (Recognizing that Wix # is built on top of WiX features, and a certain degree of understanding of WiX and the Windows installer is important: it's a comfort zone thing, the ability to use C # instead of XML, and not a completely logical thing). Currently, we perform many of these registry settings tasks manually, without a trace and a simple and reliable uninstallation.

/// <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(); } } 

}

0
source share
2 answers

You can achieve what you want by adding the <RemoveFolder> to your component in a directory that you do not want to store. See Link.

The resulting MSI will be created by light with a warning to LGHT1079 that you have no files, but can be ignored if this is the intention.

A simple XML example showing a directory with a component that deletes a folder during installation / uninstallation and creates registry keys, forcing it to be deleted during uninstallation.

 <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> 

You simply use this name for your directory or replace Directory="TARGETDIR" name of your directory.

The result after installation is a registry key without a folder on the target machine. registry keypath

You need to figure out how to get this tag in the generated XML, but the effect you need.

0
source

Using the Wix XML code provided by Ryan J, plus the “InjectXML” example from the Wix # sample code, I was able to create a wxs file and get a working MSI while still in the Wix # coding environment in Visual Studio.

Here is the corresponding .wxs XML that was generated earlier, under the element:

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

So, what should happen: 1) Remove the “item” that is in the Product / Directory / Directory / Component section. The Ryan J example clearly showed that it goes under the “Component”, which is associated with the first “Directory” created, which, in turn under "TARGETDIR" in the XML that Wix # generates.

2) Insert the element syntax, "", into the Product / Directory / Directory / Component element. Although I believe that it can also work to reference the Id "INSTALLDIR.EmptyDirectory" in this element, I used the identifier "TARGETDIR" and it worked the way I wanted.

Here is the resulting Wix # code that introduces the XML provided by Ryan J.

  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"))); } 
0
source

Source: https://habr.com/ru/post/923494/


All Articles