WiX: incomplete shortcut to command prompt - windows

I have the following shortcut definition:
<Directory Id="TARGETDIR" Name="SourceDir">
<Directory Id="ProgramFiles64Folder">
<Directory Id="INSTALLFOLDER" Name="InGenius">
<Directory Id="APPLICATIONFODLER" Name="ICE Publisher" />
</Directory>
</Directory>
<Directory Id="ProgramMenuFolder">
<Directory Id="CompanyFolder" Name="InGenius">
<Directory Id="AppFolder" Name="ICE Publisher" />
</Directory>
</Directory>
</Directory>
<DirectoryRef Id="AppFolder">
<Component Id="ApplicationShortcut" Guid="*">
<Shortcut Id="ApplicationStartMenuShortcut"
Name="App CMD Prompt"
Target="[SystemFolder]CMD.exe"
Arguments="/K [APPLICATIONFOLDER]app.bat"
WorkingDirectory="APPLICATIONFOLDER"
Show="normal"/>
<RemoveFolder Id="CompanyFolder" Directory="CompanyFolder"
On="uninstall" />
<RemoveFolder Id="AppFolder" On="uninstall" />
<RegistryValue Root="HKCU"
Key="Software\Microsoft\InGenius ICE Publisher"
Name="installed" Type="integer" Value="1" KeyPath="yes" />
</Component>
</DirectoryRef>
I get a shortcut with the following target:
C:\Windows\SysWOW64\cmd.exe /K app.bat
And nothing in the Start in: field.
I was expecting a target of:
C:\Windows\SysWOW64\cmd.exe /K c:\ProgramFiles\appfolder\app.bat
and have
c:\ProgramFiles\appfolder\app.bat
in the Start in: field
What did I do wrong?

Looks like APPLICATIONFOLDER property is not set. Check its value in debug log and set the value of APPLICATIONFOLDER property before installation starts.

Related

Wix Toolset - how to install a file to a completely different directory and not as a root subdirectory?

For my application, most of the files need to be installed to a directory in ProgramFiles, and one other file needs to be installed in a directory in AppData/Local.
Here is an example of what I have so far:
<Fragment>
<Directory Id="TARGETDIR" Name="SourceDir">
<Directory Id="ProgramFilesFolder">
<Directory Id="INSTALLFOLDER" Name="Folder1" />
</Directory>
</Directory>
</Fragment>
<Fragment>
<ComponentGroup Id="AppID" Directory="INSTALLFOLDER">
<Component Id="AppID">
<File Source="$(var.myApp.TargetPath)" />
</Component>
<Component Id="OtherFile" Guid="INSERT-GUID_HERE">
<File Id='OtherFile' Name='OtherFile' Source="otherfile" KeyPath='yes' />
</Component>
<Component Id="CopyId">
<CopyFile Id="CopyId" FileId="OtherFile"
DestinationDirectory="LocalAppDataFolder" />
</Component>
</Fragment>
I've tried to copy the other file to AppData/Local but this won't compile and gives the error:
Unresolved reference to symbol 'Directory:LocalAppDataFolder' in section 'Fragment:'
Ideally, I want the other file to be in directory in AppData/Local, and not in ProgramFiles at all.
Application Launch: Consider doing file-copying on application launch instead of as part of the setup. Easier to implement, debug and change as you need to.
Fix: Try just adding this directly under the TARGETDIR element. This ensures that the standard directory LocalAppDataFolder is part of the compiled MSI file's Directory table:
<Directory Id="LocalAppDataFolder" Name="AppData">
Alternatively, here is a larger mock-up:
<Directory Id="TARGETDIR" Name="SourceDir">
<Directory Id="ProgramFilesFolder">
<Directory Id="INSTALLFOLDER" Name="SetupProject2" />
</Directory>
<Directory Id="LocalAppDataFolder" Name="AppData">
<Directory Id="AppRootDirectory" Name="MyApplication">
<Component Id="Test" Feature="ProductFeature" Guid="{11111111-1111-1111-1111-A73067A1AE95}">
<RemoveFolder Id="AppRootDirectory" On="uninstall" />
<RegistryValue Root="HKCU" Key="Software\Something" Name="Flag" Type="integer" Value="1" KeyPath="yes"/>
</Component>
</Directory>
</Directory>
</Directory>

How to get application folder in WIX Toolkit to install service

I'm trying to to write installer for 3rd-party application.
The service should be installed and running with arguments. One of the argument it's home folder where the service was installed.
How I can read the folder where the application was installed and pass it to Wix Element: ServiceInstall as arguments.
<ServiceInstall Id="SInstall"
Type="ownProcess"
Name="myservice"
DisplayName="MyService"
EraseDescription="no"
Start="demand"
ErrorControl="normal"
Arguments="-folder '[INSTALLDIR]\config.txt'>
But [INSTALLDIR] is empty;
I suppose it's should be done by using SetProperty and read it but cannot find any references how to do this.
<Fragment>
<Directory Id="TARGETDIR" Name="SourceDir">
<Directory Id="ProgramFiles64Folder">
<Directory Id="ManufacturerFolder" Name="OEM_XXX">
<Directory Id="INSTALLFOLDER" Name="Product $(var.ProductVersion)">
<Directory Id="DirA" />
<Directory Id="DirB" Name="SubService">
<Directory Id="DirC" Name="ComponentA">
<Directory Id="ComponentB" Name="content" />
</Directory>
</Directory>
</Directory>
</Directory>
</Directory>
</Directory>
</Fragment>
<Fragment>
<DirectoryRef Id="DirB">
<Component Id="Svc1" Guid="b033eb95-ce88-48ac-b40f-6913c5e4b978" Win64="yes">
<File Source="$(var.SourceDir)\service.exe" />
<ServiceInstall Id="SInstall"
Type="ownProcess"
Name="myservice"
DisplayName="MyService"
EraseDescription="no"
Start="demand"
ErrorControl="normal"
Arguments="-folder '???????\config.txt'>
<ServiceConfig DelayedAutoStart="no" OnInstall="yes" OnReinstall ="yes" />
</ServiceInstall>
<ServiceControl Id="SControl"
Stop="both"
Remove="uninstall"
Name="myservice"
Wait="no" />
</Component>
</DirectoryRef>
</Fragment>
Thanks.
Use [{directoryId} as a reference;
In my case it was
<ServiceInstall Id="SInstall"
Type="ownProcess"
Name="myservice"
DisplayName="MyService"
EraseDescription="no"
Start="demand"
ErrorControl="normal"
Arguments='-folder "[DirB]config.txt"'>
The full list of available system folder you can find on MSDN:
https://learn.microsoft.com/en-us/windows/desktop/msi/property-reference#system-folder-properties
Sometimes names can confuse you but read description.
For example if you would like to define a path to %PROGRAMDATA% you should use [CommonAppDataFolder]
P.S. Build-in variables ends with trailing slash

ICE91 Wix in perMachine Installer

I am trying to make a perMachine Installer that is able to create files and folders in the PersonalFolder and LocalAppDataFolder of each user. I am getting always the warning message "warning LGHT1076: ICE91: ..." as listed below. When I install as an Administrator the file and folder is created despite the warning, but when I try the installer as standard user no file and no folder is created on the user profile. What could be the solution?
<Directory Id="TARGETDIR" Name="SourceDir">
<Directory Id="ProgramFilesFolder">
<Directory Id="PFInstallDir" Name="Example">
<Component Id="ApplicationFiles" Guid="12345678-1234-1234-1234-222222222222">
<File Id="ApplicationFile1" Source="notepad.exe"/>
</Component>
</Directory>
</Directory>
<Directory Id="CommonFilesFolder">
<Directory Id="CFInstallDir" Name="Example">
<Component Id="CommonApplicationFiles" Guid="12345678-1234-1234-1234-222222222223">
<File Id="ApplicationFile2" Source="notepad.exe"/>
</Component>
</Directory>
</Directory>
<Directory Id="CommonAppDataFolder">
<Directory Id="CAInstallDir" Name="Example">
<Component Id="CommonAppDataApplicationFiles" Guid="12345678-1234-1234-1234-222222222224">
<File Id="ApplicationFile3" Source="notepad.exe"/>
</Component>
</Directory>
</Directory>
<Directory Id="PersonalFolder">
<Directory Id="InstallDirPersonal" Name="ExampleDocs">
<Component Id="ApplicationPersonalFiles" Guid="12345678-1234-1234-1234-222222222225">
<CreateFolder />
<RemoveFolder Id="RemoveMyExampleDir1" On="uninstall" Directory="InstallDirPersonal"/>
<RegistryKey Root="HKCU" Key="Software\MyCompany\Documents">
<RegistryValue Name="MainExe" Value="1" KeyPath="yes" Type="integer" />
</RegistryKey>
<File Id="Notepad.MyExe"
Source="notepad.exe" DiskId="1" Checksum="yes">
</File>
</Component>
</Directory>
</Directory>
<Directory Id="LocalAppDataFolder" Name="AppData">
<Directory Id="InstallDirAppDataPersonal" Name="ExampleLocals">
<Component Id="ApplicationPersonalDataFiles" Guid="12345678-1234-1234-1234-222222222226">
<CreateFolder />
<RemoveFolder Id="RemoveMyExampleDir" On="uninstall" Directory="InstallDirAppDataPersonal"/>
<RegistryKey Root="HKCU" Key="Software\MyCompany\Example">
<RegistryValue Name="MainExe" Value="1" KeyPath="yes" Type="integer" />
</RegistryKey>
<File Id="Notepad.MyExe1"
Source="notepad.exe" DiskId="1" Checksum="yes">
</File>
</Component>
</Directory>
</Directory>
</Directory>
<Feature Id="DefaultFeature" Level="1">
<ComponentRef Id="ApplicationFiles"/>
<ComponentRef Id="CommonApplicationFiles"/>
<ComponentRef Id="CommonAppDataApplicationFiles"/>
<ComponentRef Id="ApplicationPersonalDataFiles"/>
<ComponentRef Id="ApplicationPersonalFiles"/>
</Feature>
</Product>
-- Build started: Project: SetupProjectPerUsrMachine, Configuration: Debug x86 --
warning LGHT1076: ICE91: The file 'Notepad.MyExe' will be installed to the per user directory 'InstallDirPersonal' that doesn't vary based on ALLUSERS value. This file won't be copied to each user's profile even if a per machine installation is desired.
warning LGHT1076: ICE91: The file 'Notepad.MyExe1' will be installed to the per user directory 'InstallDirAppDataPersonal' that doesn't vary based on ALLUSERS value. This file won't be copied to each user's profile even if a per machine installation is desired.
Problem solved!
http://www.installworld.com/index.php?option=com_content&do_pdf=1&id=146
"If the resource must be copied to each user’s profile, then add functionality to your package to do this. To achieve this, add a current user registry key (i.e., just a dummy registry key) and make this registry key the key path of the component which contains the resource. This means that the resource will be copied to the next user’s profile as part of the MSI self healing mechanism, provided that advertised entry points exist for the product."
http://blog.bittercoder.com/2007/02/28/wix-shortcuts/
<Component Id="StandAloneApplication" Guid="C8D5DB05-2D68-40e8-88D1-EF5BEA18DBE1">
<File Id="SomeCompanySomeProductHostApp"
Name="SomeCompany.SomeProduct.HostApp.exe"
DiskId="1"
Source="....buildSomeCompany.SomeProduct.HostApp.exe"
Vital="yes">
<Shortcut Advertise="yes"
Id="SomeCompanySomeProductHostAppShortcut"
Directory="ProgramMenuDir"
Name="My Product"
WorkingDirectory="INSTALLDIR"
Description="SomeProduct Application"
Icon="HostAppShortcutIcon.exe">
<Icon Id="HostAppShortcutIcon.exe"
SourceFile="....buildSomeCompany.SomeProduct.HostApp.exe" />
</Shortcut>
</File>
</Component>

How to copy files to CommonAppDataFolder?

In WiX I have
<Directory Id="CommonAppDataFolder">
<Directory Id="CommonAppDataManufacturerFolder" Name="$(var.MANUFACTURER)">
<Directory Id="AppDataFolder" Name="$(var.PRODUCTNAME)">
<Directory Id="DatasFolder" Name="Datas"/>
</Directory>
</Directory>
</Directory>
and
<ComponentGroup Id="DatasComponents" Directory="DatasFolder">
<Component Id="Database.sdf" Guid="4c33c78e-7113-4a8c-b9fd-6ba4f6490935">
<File Id="Database.sdf" Source="Database.sdf" />
<RemoveFolder Id='DatasFolder' On='uninstall' />
<RegistryValue Root='HKCU'
Key='Software\[Manufacturer]\[ProductName]'
Type='string'
Value=''
KeyPath='yes' />
</Component>
</ComponentGroup>
But the file is being copied to C:\Users\username\AppData\Roaming\Datas\ instead of %ProgramData%\Manufacturer\ProductName\Datas\
The problem is that AppDataFolder is a reserved keyword that takes you to the Roaming data folder, I simply changed this id to a non-reserved keyword and my code worked
<Directory Id="CommonAppDataFolder">
<Directory Id="CommonAppDataManufacturerFolder" Name="$(var.MANUFACTURER)">
<Directory Id="MyAppDataFolder" Name="$(var.PRODUCTNAME)">
<Directory Id="DatasFolder" Name="Datas"/>
</Directory>
</Directory>
</Directory>

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.

Resources