Visual Studio 2015 crashes on WiX installer build when PermissionEx is used - visual-studio

I'm trying to set folder permissions on creation. I want to modify permissions, instead of overwriting current, so I have used <PermissionEx/> tag from WiXUtilExtension instead of classic <Permission/> tag. I have added reference to WixUtilExtension.dll v4.0.0.0. WiX version is v4.0.4305.0. In WiX header I have added namespace <Wix xmlns="http://wixtoolset.org/schemas/v4/wxs" xmlns:util="http://wixtoolset.org/schemas/v4/wxs/util">. When I try to set permission like
<Component Id="CreateFolder" Directory="DIRECTORYID" Guid="MY_GUID">
<CreateFolder>
<Permission User="[LogonUser]" GenericAll="yes"/>
</CreateFolder>
</Component>
installer build succesfully.
However, when I use
<Component Id="CreateFolder" Directory="DIRECTORYID" Guid="MY_GUID">
<CreateFolder>
<util:PermissionEx User="[LogonUser]" GenericAll="yes"/>
</CreateFolder>
</Component>
installer build stops with exception
and Visual Studio 2015 Community Edition crashes completely.
Directory is created like:
<Fragment>
<Directory Id="TARGETDIR" Name="SourceDir">
<Directory Id="ProgramFilesFolder" >
<Directory Id="APPLICATIONFOLDER" >
<Directory Id="DIRECTORYID" Name="TestDir"/>
</Directory>
</Directory>
</Directory>
</Fragment>
Do you have any clues, if I am something doing wrong, or it is bug in newest WiX build?

Related

WiX: preserving recursive directory structure during component transfer

Wix 3.11.2 and Visual Studio Community 2019 here. My project has the following directory structure:
...\Source\Repos\my-app-setup\
my-app-setup\
bin\
obj\
testo\
fizz\
abc\
def\
ghi\
abba.txt
buzz\
bar.txt
foo.txt
my-app.exe
my-app-setup.wixproj
my-app-setup.wxs
my-app-setup.sln
Where my my-app-setup.wxs file is as follows:
<?xml version="1.0" encoding="UTF-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">​
<Product Id="*" Name="MyApp" Language="1033" Version="1.0.0.0" Manufacturer="MyCompany" UpgradeCode="1e540666-dda2-4cbe-91b7-ac9525d96c86">​
<Package Description="MyApp tool" Compressed="yes" />​
​
<MediaTemplate EmbedCab="yes"/>​
​
<Directory Id="TARGETDIR" Name="SourceDir">​
<Directory Id="ProgramFilesFolder">​
<Directory Id="INSTALLFOLDER" Name="MyApp" />​
</Directory>​
​
<Directory Id="DesktopFolder" Name="Desktop">​
<Component Id="ApplicationShortcutDesktop" Guid="*">​
<Shortcut Id="ApplicationDesktopShortcut"​
Name="MyApp"​
Description="Shortcut for MyApp"​
Target="[INSTALLFOLDER]my-app.exe"​
WorkingDirectory="INSTALLFOLDER"/>​
<RemoveFolder Id="DesktopFolder" On="uninstall"/>​
<RegistryValue​
Root="HKCU"​
Key="Software/MyApp"​
Name="installed"​
Type="integer"​
Value="1"​
KeyPath="yes"/>​
</Component>​
</Directory>​
</Directory>​
​
<Component Id="FooTxtComponent" Directory="INSTALLFOLDER">​
<File Source="testo/foo.txt" />​
</Component>​
​
<Component Id="AbbaComponent" Directory="INSTALLFOLDER">​
<File Source="testo/fizz/abc/def/ghi/abba.txt" />​
</Component>​
​
<Component Id="ExecutableComponent" Directory="INSTALLFOLDER">​
<File Source="my-app.exe" />​
</Component>​
<Feature Id="MainFeature" Title="MyApp" Level="1">​
<ComponentRef Id="FooTxtComponent" />​
<ComponentRef Id="AbbaComponent" />​
<ComponentRef Id="ExecutableComponent" />
​
<ComponentRef Id="ApplicationShortcutDesktop" />​
</Feature>​
</Product>​
</Wix>
So it basically just copies a bunch of files from the project into the C:\Program Files (x86)\MyApp directory and then creates a shortcut (to the EXE) on the desktop. Simple stuff.
When I build this and run the MSI the resulting C:\Program Files (x86)\MyApp directory looks like this:
C:\Program Files (x86)\
MyApp\
foo.txt
abba.txt
my-app.exe
So WiX is just plucking the files I specified and dropping them into the MyApp directory, at the same level as the EXE file. I don't want this; I want to preserve the same recursive directory structure as what exists in my VS project. So instead of the above I would like the WiX MSI to generate:
C:\Program Files (x86)\
MyApp\
testo\
fizz\
abc\
def\
ghi\
abba.txt
foo.txt
my-app.exe
What is the simplest way to accomplish this?
Thanks!
You need to nest the folders as shown in this sample (towards bottom): https://www.codeproject.com/Tips/105638/A-quick-introduction-Create-an-MSI-installer-with
Illustration:
<Directory Id="TARGETDIR" Name="SourceDir">
<Directory Id="ProgramFilesFolder">
<Directory Id="INSTALLDIR" Name="Example">
<Component>
<File Source="example.exe"/>
</Component>
</Directory>
</Directory>
</Directory>
Maybe also check:
My WiX Quick-Start Link Collection.
https://www.firegiant.com/wix/tutorial/

WIX setup with user input

I've struggled with WIX for some time now. I want my program to be installed at the location the user has defined, install a service and start a program after installation.
First my msi package doesn't ask for install path.
<Fragment>
<Directory Id="TARGETDIR" Name="SourceDir">
<Directory Id="ProgramFilesFolder">
<Directory Id="INSTALLFOLDER" Name="Test" />
</Directory>
</Directory>
</Fragment>
May someone tell me how to prompt a screen with change install path?
Second when my service will be installed there is an error which says I miss some permissions:
<File Id="FILE_Service" Source="$(var.Service.TargetPath)" />
<ServiceInstall Id="INSTALL_Service"
Name="Servcie"
Description=""
Start="auto"
ErrorControl="normal"
Type="ownProcess"/>
<ServiceControl Id="CONTROL_Service"
Name="Servcie"
Start="install"
Stop="both"
Remove="uninstall"
Wait="yes" />
May someone tell me how to start my service with admin access?
Third the installed package contains only one EXE file, no referenced assembly. May someone tell me how to tell WIX to search for references and install them?
WiX Tutorial: Quite a bit here. You should try a WiX tutorial: https://www.firegiant.com/wix/tutorial/
Links: Here is my WiX quick start tip answer - various resources and hints to deal with WiX and deployment in general.
Please note that there are alternative deployment and package creation tools that might help you make setups quicker and more reliably if you have little experience with MSI and setups.
Learning Advanced Installer - Resources
Direct link Advanced Installer Video Tutorials
Concrete Answer: Here are some attempted answers for your concrete questions:
Configurable installation directory (a bit down the page). You essentially set the ConfigurableDirectory attribute for a feature element to allow the user to select a custom installation directory (you get to the dialog where you can change the installation path by selecting "Custom" installation):
<Feature Id="FeatureDirectory" Title="FeatureDirectory" ConfigurableDirectory="MYCUSTOMDIR">
<!-- your stuff here -->
</Feature>
Major Upgrade Installation Directory: You need to read back the custom directory for major upgrades. Here is how: The WiX toolset's "Remember Property" pattern. Or it will revert to default during the major upgrade. This is because a major upgrade is an uninstall of the old version and a (re)-install of the new version.
Files: To install all required files you need to figure out by dependency scanning what files need to be deployed for your application to work, and then add them to your packages manually (or use heat.exe to auto-generate the files list to include). See the above quick start links for help, or see this hello wix style article: https://www.codeproject.com/Tips/105638/A-quick-introduction-Create-an-MSI-installer-with
Service Permissions: Services should be installed with admin rights if you install the setup after a UAC elevation prompt. Most likely it does not start because there are missing files and hence broken dependencies. What credentials does the service use to run? LocalSystem?
Mock-Up: Here is a quick mock-up of something along the lines of what you need. You need to add all files and dependencies and insert the Service constructs among other things:
<?xml version="1.0" encoding="UTF-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
<Product Id="*" Name="WiXSample" Language="1033" Version="1.0.0.0"
Manufacturer="Someone" UpgradeCode="cb24bedf-e361-4f25-9a06-ac84ce5d6f5c">
<Package InstallerVersion="200" Compressed="yes" InstallScope="perMachine" />
<MajorUpgrade DowngradeErrorMessage="A newer version of [ProductName] is already installed." />
<MediaTemplate EmbedCab="yes" />
<!--Default GUI - add reference to WixUIExtension.dll -->
<UIRef Id="WixUI_Mondo" />
<Feature Id="Core" Title="Core" Level="1" ConfigurableDirectory="INSTALLFOLDER" />
<Directory Id="TARGETDIR" Name="SourceDir">
<Directory Id="ProgramFilesFolder">
<Directory Id="INSTALLFOLDER" Name="WiXSample">
<Component Feature="Core">
<File Source="D:\MyBinary.exe" />
</Component>
</Directory>
</Directory>
</Directory>
</Product>
</Wix>

Get file version of the running exe installer

I'm using Wix for my application installation and I trying to add to installation the Build Number from TFS as text in on of the dialogs.
All my application dll's and the installer itself has the build number as their file version.
I was able to accomplish this only by getting a file version of an existing EXE(from this post: Getting the file version of a native exe in MSBuild) but not of the running EXE.
<?define Property_ProductVersion = "!(bind.FileVersion.UXIDTEST)" ?>
<Product Id="$(var.ProductId)" Name="$(var.ProductDisplayName)" Language="1033" Version="$(var.Property_ProductVersion)" Manufacturer="$(var.Property_Manufacturer)" UpgradeCode="$(var.ProductUpgradeCode)">
<Package InstallerVersion="300" Compressed="yes" InstallScope="perMachine" InstallPrivileges="elevated" />
<Directory Id='TARGETDIR' Name='SourceDir'>
<Directory Id='xxx'>
<Component Id='ttt' Guid='{AA2A781C-2324-4F9C-B96C-DCB5BB643409}'>
<File Id="UXIDTEST" Source="OriginalDatabase" ></File>
</Component>
</Directory>
</Directory>
What can I use to get the file version of the running EXE?

VS2010 Wix proj - How to pass a command line variable to be used as a directory name

We have a requirement to install the same software in multiple directories on the same machine. I want to install the software using a batch file. I am having difficulty using the variable I have passed in as a directory name. (I am using VS 2010).
Batch file code
msiexec /i "SetupProjectTestMultiInstalls.msi" CUSTOMER="TESTCUSTOMER"
However the path created is
C:\Program Files\SetupProjectTestMultiInstalls[CUSTOMER]
as oppose to what I want
C:\Program Files\SetupProjectTestMultiInstalls\TESTCUSTOMER
Here is my wix xml
<Media Id="1" Cabinet="media1.cab" EmbedCab="yes" />
<?define MYVARIABLE = "Temp" ?>
<?define FORMDIR = "$(var.SolutionDir)WindowsFormsApplication1\bin\Debug\"?>
<Condition Message="CUSTOMER variable must be set in the command line">
CUSTOMER
</Condition>
<Directory Id="TARGETDIR" Name="SourceDir">
<Directory Id="ProgramFilesFolder">
<Directory Id="INSTALLLOCATION" Name="SetupProjectTestMultiInstalls">
<Directory Id="Customer" Name="[CUSTOMER]">
<Component Id="ConfigFiles" Guid ="4fdbee76-d149-11df-aa02-05feded72085">
<File Id="WindowsFormsApplication1.exe" DiskId ="1" Vital="yes" ReadOnly="no"
Name="WindowsFormsApplication1.exe"
Source ="$(var.FORMDIR)WindowsFormsApplication1.exe" />
</Component>
</Directory>
</Directory>
</Directory>
</Directory>
<Feature Id="ProductFeature" Title="SetupProjectTestMultiInstalls" Level="1">
<ComponentGroupRef Id="Product.Generated" />
<ComponentRef Id="ConfigFiles" />
</Feature>
</Product>
Any ideas
Thanks
Jake
You can do something like this using INSTALLDIR instead of CUSTOMER to pass the location from the command line :
msiexec /i "SetupProjectTestMultiInstalls.msi" INSTALLDIR="C:\Program Files\SetupProjectTestMultiInstalls\TESTCUSTOMER"
<Directory Id="TARGETDIR" Name="SourceDir">
<Directory Id="ProgramFilesFolder">
<Directory Id="INSTALLDIR" Name=".">
<Component Id="ConfigFiles" Guid ="4fdbee76-d149-11df-aa02-05feded72085">
<File Id="WindowsFormsApplication1.exe" DiskId ="1" Vital="yes" ReadOnly="no"
Name="WindowsFormsApplication1.exe"
Source ="$(var.FORMDIR)WindowsFormsApplication1.exe" />
</Component>
</Directory>
</Directory>
</Directory>
However, I don't think that you can run the installer several times to install the software to different places. If the Product Id is already used then it will probably do a repair instead of a fresh install.

How to remove custom actions binary on uninstallation?

When I'm uninstalling my product directory where custom action binary was placed stays. How can I delete it. Also strange named directory is created on installation - unistallation: "RSCustomActions.CA.dll-" and "RSCustomActions.CA.dll-0" (my binary name RSCustomActions.CA.dll)
My WIX code is
<Directory Id="TARGETDIR" Name="SourceDir">
<Directory Id="ProgramFilesFolder">
<Directory Id="Product.Id" Name="Product">
<Directory Id="INSTALLLOCATION" Name="Product">
<!-- TEST -->
<Directory Id="Installer" Name="Installer">
<Component Id="InstallerFiles"
Guid="{0904DB36-2496-419c-A992-B7D86F068F12}">
<File Id="RSCustomActions.CA.dll" Name="RSCustomActions.CA.dll" Source="Binaries\RSCustomActions.CA.dll" />
</Component>
</Directory>
<!-- END TEST -->
<?include "Product.Files.wxi" ?>
</Directory>
</Directory>
</Directory>
<Directory Id="ProgramMenuFolder" Name="PMenu">
<Directory Id="ProgramMenuDir" Name="Aspose">
<?include "Product.ProgramMenu.wxi" ?>
</Directory>
</Directory>
<Component Id="Main" Shared="yes" Guid="{EDD4477A-D188-469c-B8D0-4423377C03C6}" Feature="Main.InstallFeatures">
<RemoveFolder Id="DeleteProgramMenuDir" Directory="ProgramMenuDir" On="uninstall" />
</Component>
</Directory>
"Product.Files.wxi" also contains
<Component Id="Product.Remove" Guid="{C6D9D74C-66E8-442a-8E53-78A8D0E2B24D}">
<RemoveFolder Id="Product.RemoveFolder.Action" On="uninstall"/>
</Component>
Please suggest any way how can I remove Installer folder and those strage folders with binary name.
Thanks!
Why do you need installing the CA DLL as a file of the product? You can simply put it to Binary table and forget about it, like this:
<!-- This is a reference to the DLL where all custom actions reside -->
<Binary Id="CustomActions" SourceFile="$(var.Root)\CA\CustomActions.CA.dll" />
And the custom action definition is something like this:
<!-- Sample CA definition -->
<CustomAction Id="MyAction" BinaryKey="CustomActions" DllEntry="MyActionMethod" />
Note that MyActionMethod should be defined in that CA assembly and marked appropriately. There's a good sample of this in dtf.chm in WiX distribution.
Hope this helps.

Resources