Writing To Registry Using SID For Permission Instead Of Group Name - wix

When writing a registry value, is there a way to use the SID instead of the group name? E.g. currently I have:
<Component Id="RegistryEntries" Guid="{------sanitized------}">
<RegistryKey Root="HKLM" Key="------sanitized------" ForceCreateOnInstall="yes">
<Permission User="Users" GenericRead="yes" Read="yes" GenericWrite="yes" />
<RegistryValue Name="ServerName" Action="write" Type="string" Value="" KeyPath="yes">
<Permission User="Users" GenericRead="yes" Read="yes" GenericWrite="yes" />
</RegistryValue>
</RegistryKey>
</Component>
which normally works, but fails in non-English languages, because of the "Users" name being translated. If I change the Permission elements to the SIDs, it should work (imo) but it does not:
<Component Id="RegistryEntries" Guid="{------sanitized------}">
<RegistryKey Root="HKLM" Key="------sanitized------" ForceCreateOnInstall="yes">
<Permission User="S-1-5-32-545" GenericRead="yes" Read="yes" GenericWrite="yes" />
<RegistryValue Name="ServerName" Action="write" Type="string" Value="" KeyPath="yes">
<Permission User="S-1-5-32-545" GenericRead="yes" Read="yes" GenericWrite="yes" />
</RegistryValue>
</RegistryKey>
</Component>
Instead it tries to search for a group literally called "S-1-5-32-545". Is there a way to do what I'm trying to do here? I know other non-wix installers can do this, but there is no information in the wix documentation on such things.

I had a very similar problem and could solve it:
Using <PermissionEx> from the Wix Util Extension instead of using
<Permission>.
Using the built-in custom action
WixQueryOsWellKnownSID to get the localized name of the Users group.
First, you need to add the WixUtilExtension reference to your project.
Then, you need to add the WixUtil namespace to your wxs source file:
xmlns:util="http://schemas.microsoft.com/wix/UtilExtension"
So now you can use the PermissionEx element from the Wix Util Extension:
<util:PermissionEx User="[WIX_ACCOUNT_USERS]" GenericAll="yes" />
To make the property WIX_ACCOUNT_USERS available, you need to (implicitly) call the built-in custom action WixQueryOsWellKnownSID by adding a property reference to your <Product>:
<PropertyRef Id="WIX_ACCOUNT_USERS" />
This works for me using Wix 3.10 on Windows 10 (English and German)

Related

How can I get my WiX product script to correctly install my active x control?

The situation
I have written a custom Active X control for use within another, NON-WEB, application. when I manually run "regasm /codebase MyMacTest.dll" the control is registered and it can be used within the application using a jscript interpreter. This means I need to create an ActiveXObject etc... .
So my next step is to create an install MSI using Wix toolset 3.11. According to what I have read I need to run Heat against the dll to create the output wxs content. I did that and added it to my product.wxs compiled and ran. It deployed my dll correctly, verified the registry entry however it is Not working in the application.
My c# code:
using System;
using System.Runtime.InteropServices;
namespace MyMacTest
{
[ProgId("MyMacTest.MacroTest")]
[ClassInterface(ClassInterfaceType.None)]
[Guid("765563f5-55b0-41e1-9f49-311ec88f6ba2")]
[ComVisible(true)]
public class MacroTest
{
public MacroTest()
{
}
public string GetMessage()
{
return $"This is a test for {DateTime.Now}";
}
}
}
The Heat output for the compiled DLL:
<?xml version="1.0" encoding="utf-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
<Fragment>
<DirectoryRef Id="TARGETDIR">
<Directory Id="dir39B22699688E51DCD8DCBB99A47E835B" Name="Debug" />
</DirectoryRef>
</Fragment>
<Fragment>
<DirectoryRef Id="dir39B22699688E51DCD8DCBB99A47E835B">
<Component Id="cmp88AF0B935698304B52D96A0CEA4F7661" Guid="PUT-GUID-HERE">
<Class Id="{765563F5-55B0-41E1-9F49-311EC88F6BA2}" Context="InprocServer32" Description="MyMacTest.MacroTest" ThreadingModel="both" ForeignServer="mscoree.dll">
<ProgId Id="MyMacTest.MacroTest" Description="MyMacTest.MacroTest" />
</Class>
<File Id="filC0F476996EBA80AC7C8F27AA886F48E0" KeyPath="yes" Source="SourceDir\Debug\MyMacTest.dll" />
<RegistryValue Root="HKCR" Key="CLSID\{765563F5-55B0-41E1-9F49-311EC88F6BA2}\Implemented Categories\{62C8FE65-4EBB-45e7-B440-6E39B2CDBF29}" Value="" Type="string" Action="write" />
<RegistryValue Root="HKCR" Key="CLSID\{765563F5-55B0-41E1-9F49-311EC88F6BA2}\InprocServer32\1.0.0.0" Name="Class" Value="MyMacTest.MacroTest" Type="string" Action="write" />
<RegistryValue Root="HKCR" Key="CLSID\{765563F5-55B0-41E1-9F49-311EC88F6BA2}\InprocServer32\1.0.0.0" Name="Assembly" Value="MyMacTest, Version=1.0.0.0, Culture=neutral, PublicKeyToken=583df5a1a2a0a8da" Type="string" Action="write" />
<RegistryValue Root="HKCR" Key="CLSID\{765563F5-55B0-41E1-9F49-311EC88F6BA2}\InprocServer32\1.0.0.0" Name="RuntimeVersion" Value="v4.0.30319" Type="string" Action="write" />
<RegistryValue Root="HKCR" Key="CLSID\{765563F5-55B0-41E1-9F49-311EC88F6BA2}\InprocServer32\1.0.0.0" Name="CodeBase" Value="file:///[#filC0F476996EBA80AC7C8F27AA886F48E0]" Type="string" Action="write" />
<RegistryValue Root="HKCR" Key="CLSID\{765563F5-55B0-41E1-9F49-311EC88F6BA2}\InprocServer32" Name="Class" Value="MyMacTest.MacroTest" Type="string" Action="write" />
<RegistryValue Root="HKCR" Key="CLSID\{765563F5-55B0-41E1-9F49-311EC88F6BA2}\InprocServer32" Name="Assembly" Value="MyMacTest, Version=1.0.0.0, Culture=neutral, PublicKeyToken=583df5a1a2a0a8da" Type="string" Action="write" />
<RegistryValue Root="HKCR" Key="CLSID\{765563F5-55B0-41E1-9F49-311EC88F6BA2}\InprocServer32" Name="RuntimeVersion" Value="v4.0.30319" Type="string" Action="write" />
<RegistryValue Root="HKCR" Key="CLSID\{765563F5-55B0-41E1-9F49-311EC88F6BA2}\InprocServer32" Name="CodeBase" Value="file:///[#filC0F476996EBA80AC7C8F27AA886F48E0]" Type="string" Action="write" />
</Component>
</DirectoryRef>
</Fragment>
My modified product with the heat fragment:
<?xml version="1.0" encoding="UTF-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi"><?define MyMacTest_TargetDir=$(var.MyMacTest.TargetDir)?>
<Product Id="*" Name="MyMacSetup"
Language="1033"
Version="1.0.0.0"
Manufacturer="Mega Software Stuff"
UpgradeCode="b3e8921b-22da-4f05-a79f-36cafde09fce">
<Package InstallerVersion="200" Compressed="yes" InstallScope="perMachine" />
<MajorUpgrade DowngradeErrorMessage="A newer version of [ProductName] is already installed." />
<MediaTemplate EmbedCab="yes"/>
<Feature Id="ProductFeature" Title="MyMacSetup" Level="1">
<ComponentGroupRef Id="ProductComponents" />
<ComponentRef Id="cmp88AF0B935698304B52D96A0CEA4F7661"/>
</Feature>
</Product>
<Fragment>
<Directory Id="TARGETDIR" Name="SourceDir">
<Directory Id="ProgramFilesFolder">
<Directory Id="Bp" Name="BPE">
<Directory Id="Addin" Name="AddIns">
<Directory Id="INSTALLFOLDER" Name="MyCustom" />
</Directory>
</Directory>
</Directory>
</Directory>
</Fragment>
<Fragment>
<ComponentGroup Id="ProductComponents" Directory="INSTALLFOLDER">
<Component Id="MyMacTest.dll" Guid="21b3cee3-1da3-4f48-89db-7c2f6cf11431">
<File Id="MyMacTest.dll" Name="MyMacTest.dll" Source="$(var.MyMacTest_TargetDir)MyMacTest.dll" />
</Component>
</ComponentGroup>
</Fragment>
<!-- This segment gotten from heat: "c:\Program Files (x86)\WiX Toolset v3.11\bin\heat" file MyMacTest.dll -out mymactest.wxs -->
<Fragment>
<DirectoryRef Id="INSTALLFOLDER">
<Component Id="cmp88AF0B935698304B52D96A0CEA4F7661" Guid="b33671b4-2f75-44bc-8435-f16c5f9b7268">
<Class Id="{765563F5-55B0-41E1-9F49-311EC88F6BA2}" Context="InprocServer32" Description="MyMacTest.MacroTest" ThreadingModel="both" ForeignServer="mscoree.dll">
<ProgId Id="MyMacTest.MacroTest" Description="MyMacTest.MacroTest" />
</Class>
<!--<File Id="filC0F476996EBA80AC7C8F27AA886F48E0" KeyPath="yes" Source="$(var.MyMacTest_TargetDir)MyMacTest.dll" />-->
<RegistryValue Root="HKCR" Key="CLSID\{765563F5-55B0-41E1-9F49-311EC88F6BA2}\Implemented Categories\{62C8FE65-4EBB-45e7-B440-6E39B2CDBF29}" Value="" Type="string" Action="write" />
<RegistryValue Root="HKCR" Key="CLSID\{765563F5-55B0-41E1-9F49-311EC88F6BA2}\InprocServer32\1.0.0.0" Name="Class" Value="MyMacTest.MacroTest" Type="string" Action="write" />
<RegistryValue Root="HKCR" Key="CLSID\{765563F5-55B0-41E1-9F49-311EC88F6BA2}\InprocServer32\1.0.0.0" Name="Assembly" Value="MyMacTest, Version=1.0.0.0, Culture=neutral, PublicKeyToken=583df5a1a2a0a8da" Type="string" Action="write" />
<RegistryValue Root="HKCR" Key="CLSID\{765563F5-55B0-41E1-9F49-311EC88F6BA2}\InprocServer32\1.0.0.0" Name="RuntimeVersion" Value="v4.0.30319" Type="string" Action="write" />
<RegistryValue Root="HKCR" Key="CLSID\{765563F5-55B0-41E1-9F49-311EC88F6BA2}\InprocServer32\1.0.0.0" Name="CodeBase" Value="file:///[#MyMacTest.dll]" Type="string" Action="write" />
<RegistryValue Root="HKCR" Key="CLSID\{765563F5-55B0-41E1-9F49-311EC88F6BA2}\InprocServer32" Name="Class" Value="MyMacTest.MacroTest" Type="string" Action="write" />
<RegistryValue Root="HKCR" Key="CLSID\{765563F5-55B0-41E1-9F49-311EC88F6BA2}\InprocServer32" Name="Assembly" Value="MyMacTest, Version=1.0.0.0, Culture=neutral, PublicKeyToken=583df5a1a2a0a8da" Type="string" Action="write" />
<RegistryValue Root="HKCR" Key="CLSID\{765563F5-55B0-41E1-9F49-311EC88F6BA2}\InprocServer32" Name="RuntimeVersion" Value="v4.0.30319" Type="string" Action="write" />
<RegistryValue Root="HKCR" Key="CLSID\{765563F5-55B0-41E1-9F49-311EC88F6BA2}\InprocServer32" Name="CodeBase" Value="file:///[#MyMacTest.dll]" Type="string" Action="write" />
</Component>
</DirectoryRef>
</Fragment>
</Wix>
My question on all of this:
After spending a couple of days I have found that there seem to be a lot of messages on this, but nothing that gives me a step by step example or explanation on how to create a wix script that will perform the "regasm /codebase" that I need to do. Kind of confusing. This is my first wix/MSI project.
What am I missing and/or what do I need to know to make this work? Is there a good step by step somewhere, that i haven't found yet, that I can be pointed to?
Update with diffs
manual registration with regasm /codebase
[HKEY_CLASSES_ROOT\CLSID\{765563F5-55B0-41E1-9F49-311EC88F6BA2}]
#="MyMacTest.MacroTest"
[HKEY_CLASSES_ROOT\CLSID\{765563F5-55B0-41E1-9F49-311EC88F6BA2}\Implemented Categories]
[HKEY_CLASSES_ROOT\CLSID\{765563F5-55B0-41E1-9F49-311EC88F6BA2}\Implemented Categories\{62C8FE65-4EBB-45e7-B440-6E39B2CDBF29}]
[HKEY_CLASSES_ROOT\CLSID\{765563F5-55B0-41E1-9F49-311EC88F6BA2}\InprocServer32]
#="mscoree.dll"
"ThreadingModel"="Both"
"Class"="MyMacTest.MacroTest"
"Assembly"="MyMacTest, Version=1.0.0.0, Culture=neutral, PublicKeyToken=583df5a1a2a0a8da"
"RuntimeVersion"="v4.0.30319"
"CodeBase"="file:///C:/Users/Kevin/OneDrive/Documents/MyMacTest.DLL"
[HKEY_CLASSES_ROOT\CLSID\{765563F5-55B0-41E1-9F49-311EC88F6BA2}\InprocServer32\1.0.0.0]
"Class"="MyMacTest.MacroTest"
"Assembly"="MyMacTest, Version=1.0.0.0, Culture=neutral, PublicKeyToken=583df5a1a2a0a8da"
"RuntimeVersion"="v4.0.30319"
"CodeBase"="file:///C:/Users/Kevin/OneDrive/Documents/MyMacTest.DLL"
[HKEY_CLASSES_ROOT\CLSID\{765563F5-55B0-41E1-9F49-311EC88F6BA2}\ProgId]
#="MyMacTest.MacroTest"
===========================================
msi install
[HKEY_CLASSES_ROOT\WOW6432Node\CLSID\{765563F5-55B0-41E1-9F49-311EC88F6BA2}]
#="MyMacTest.MacroTest"
[HKEY_CLASSES_ROOT\WOW6432Node\CLSID\{765563F5-55B0-41E1-9F49-311EC88F6BA2}\Implemented Categories]
[HKEY_CLASSES_ROOT\WOW6432Node\CLSID\{765563F5-55B0-41E1-9F49-311EC88F6BA2}\Implemented Categories\{62C8FE65-4EBB-45e7-B440-6E39B2CDBF29}]
#=""
[HKEY_CLASSES_ROOT\WOW6432Node\CLSID\{765563F5-55B0-41E1-9F49-311EC88F6BA2}\InprocServer32]
#="mscoree.dll"
"ThreadingModel"="Both"
"Class"="MyMacTest.MacroTest"
"Assembly"="MyMacTest, Version=1.0.0.0, Culture=neutral, PublicKeyToken=583df5a1a2a0a8da"
"RuntimeVersion"="v4.0.30319"
"CodeBase"="file:///C:\\Program Files (x86)\\BPE\\AddIns\\MyCustom\\MyMacTest.dll"
[HKEY_CLASSES_ROOT\WOW6432Node\CLSID\{765563F5-55B0-41E1-9F49-311EC88F6BA2}\InprocServer32\1.0.0.0]
"Class"="MyMacTest.MacroTest"
"Assembly"="MyMacTest, Version=1.0.0.0, Culture=neutral, PublicKeyToken=583df5a1a2a0a8da"
"RuntimeVersion"="v4.0.30319"
"CodeBase"="file:///C:\\Program Files (x86)\\BPE\\AddIns\\MyCustom\\MyMacTest.dll"
[HKEY_CLASSES_ROOT\WOW6432Node\CLSID\{765563F5-55B0-41E1-9F49-311EC88F6BA2}\ProgID]
#="MyMacTest.MacroTest"
Not sure why the MSI install added WOW6432Node to the paths... but these are the differences.
Thanks!
UPDATE: Be aware that COM is bitness aware. In your example you are building a 32bit MSI that will install the COM server in the 32bit registry. You may be calling it from a 64bit process and that would not work.
The way you are doing generally works. To troubleshoot you will want to:
1) Create a VM and snapshot it
2) Install your MSI
3) Run a registry diff tool such as Install Watch Pro or InControl. Take a snapshot of the registry.
4) Manually run your regasm /codebase command from an elevated command prompt.
5) Take another snapshot of the registry and run a diff report.
6) Examine the differences for meaningful relevant differences and author them into your WXS source.
7) Rebuild the MSI
8) Apply the VM Snapshot to get back to a clean state.
9) Install the MSI and retest functionality.
If you are wondering why heat didn't work by itself the answer has to do with COM. Sometimes the sniffing techniques just don't work. In the case of .NET COM Interop / COM Visible assemblies sometimes the answer lies in this caveat. In your case this might have to do with your use of the ClassInterface attribute.
https://learn.microsoft.com/en-us/dotnet/framework/tools/regasm-exe-assembly-registration-tool
You can use the /regfile option to generate a .reg file that contains
the registry entries instead of making the changes directly to the
registry. You can update the registry on a computer by importing the
.reg file with the Registry Editor tool (Regedit.exe). Note that the
.reg file does not contain any registry updates that can be made by
user-defined register functions. Note that the /regfile option only
emits registry entries for managed classes. This option does not emit
entries for TypeLibIDs or InterfaceIDs.
If you are unable to resolve this, I have 25 years experience working through these types of issues. If you are able to share the DLL and give me a code snippet to smoke test with I could create a WiX snippet that properly registers the assembly.
PS- I would merge those two components. The COM/Registry elements should belong to the same component as the file they are for.

How to add several ports to FirewallException in Wix?

I use property PORTS to pass some http ports to my installation.
Then these ports will be stored into init file and used by the application.
I need to add these ports to FirewallException?
But following code does not work:
<Component Id="fwException" Guid="MyGUID">
<Condition>Privileged</Condition>
<RegistryKey Root="HKCU" Key="Software\Company\[ProductName]">
<RegistryValue Name="fwException" Value="1" KeyPath="yes" Type="integer" />
</RegistryKey>
<fire:FirewallException Id="My_Ports" Name="My Node.exe" Profile="domain" Port="[PORTS]" Protocol="tcp" Scope="localSubnet"/>
</Component>
How to add several ports to FirewallException?
Summary
In WIX 3.9 (and earlier), the FirewallExtension only supports a single integer for the Port attribute. The Port attribute supports Formatted values, but the result of the formatting must still be a single integer. In your case [PORTS] must evaluate to a single integer.
If the Port attribute is set to 'Not a number', you would typically see this error in the installation log:
SchedFirewallException: Error 0x80070057: failed to parse record field: 3 as number: Not a number
From #Sean's comment, multiple ports should work in WIX 3.10. See http://wixtoolset.org/issues/4206/ for details of the feature request.
Workaround for WIX 3.9 and Earlier
It is possible to work around this restriction by using FirewallExtension delcarations:
<Component Id="fwException" Guid="-- YOUR GUID --">
<Condition>Privileged</Condition>
<RegistryKey Root="HKCU" Key="Software\Company\[ProductName]">
<RegistryValue Name="fwException" Value="1" KeyPath="yes" Type="integer" />
</RegistryKey>
<fire:FirewallException Id="My_Port1" Name="My Node.exe" Profile="domain" Port="[PORT1]" Protocol="tcp" Scope="localSubnet"/>
<fire:FirewallException Id="My_Port2" Name="My Node.exe" Profile="domain" Port="[PORT2]" Protocol="tcp" Scope="localSubnet"/>
</Component>
If you need a variable number of ports (up to a pre-defined maximum limit) you could try 1 firewall extension per component with a condition on each component:
<Component Id="fwException1" Guid="-- YOUR GUID --">
<Condition>Privileged AND PORT1</Condition>
<RegistryKey Root="HKCU" Key="Software\Company\[ProductName]">
<RegistryValue Name="fwException1" Value="1" KeyPath="yes" Type="integer" />
</RegistryKey>
<fire:FirewallException Id="My_Port1" Name="My Node.exe" Profile="domain" Port="[PORT1]" Protocol="tcp" Scope="localSubnet"/>
</Component>
<Component Id="fwException2" Guid="-- YOUR GUID --">
<Condition>Privileged AND PORT2</Condition>
<RegistryKey Root="HKCU" Key="Software\Company\[ProductName]">
<RegistryValue Name="fwException2" Value="1" KeyPath="yes" Type="integer" />
</RegistryKey>
<fire:FirewallException Id="My_Port2" Name="My Node.exe" Profile="domain" Port="[PORT2]" Protocol="tcp" Scope="localSubnet"/>
</Component>
From the command line you would specify multiple ports as: PORT1=7071, PORT2=7072, and so on. How suitable this is depends on the maximum number of ports you need to specify.

Register 32-Bit COM Class in 64-Bit Component

I have built a ContextMenuHandler for the Windows Explorer shell using SharpShell. The assembly is built for AnyCPU, i.e. in MSIL, and can therefore run as both 32 bit and 64 bit.
I intend to run this on 64 bit windows only, however, 32 bit applications on windows 64 still use the 32 bit version of the shell for open dialogs, etc.
I have registered this assembly manually using the regasm tool on both architectures (32 & 64) and it works fine in the 64bit windows explorer. It also works from file open, and other shell provided dialogs, in 32 bit applications. This is the intended behavior, great!
The problem I have is writing the installation script, I'm using Wix 3.7 and I don't want to use regasm.
The 64 bit component is installed with:-
<Component Id="cmpMyAssembly64" Directory="INSTALL_TO_HERE"
Location="local" Win64="yes">
<File Id="filMyAssembly" KeyPath="yes" Source="mySource.dll"
Assembly=".net" AssemblyApplication="filMyAssembly"
ProcessorArchitecture="msil"/>
<Class Id="01201201-0000-0000-0000-012345670123" Description="My Handler"
Context="InprocServer32" ThreadingModel="both" ForeignServer="mscoree.dll">
<ProgId Id="A.ContextHandler" Description="Does something" />
</Class>
<RegistryKey Root="HKCR" Key="CLSID\{01201201-0000-0000-0000-012345670123}"
ForceCreateOnInstall="yes" ForceDeleteOnUninstall="yes">
<RegistryKey Key="Implemented Categories\{62C8FE65-4EBB-45e7-B440-6E39B2CDBF29}">
<RegistryValue Value="" Type="string" />
</RegistryKey>
<RegistryKey Key="InprocServer32">
<RegistryKey Key="1.0.0.0">
<RegistryValue Name="Class" Value="aNamespace.theClass" Type="string" />
<RegistryValue Name="Assembly" Value="!(bind.assemblyFullName.filMyAssembly)" Type="string" />
<RegistryValue Name="RuntimeVersion" Value="v4.0.30319" Type="string" />
<RegistryValue Name="CodeBase" Value="file:///[#filMyAssembly]" Type="string" />
</RegistryKey>
<RegistryValue Name="Class" Value="aNamespace.theClass" Type="string" />
<RegistryValue Name="Assembly" Value="!(bind.assemblyFullName.filMyAssembly)" Type="string" />
<RegistryValue Name="RuntimeVersion" Value="v4.0.30319" Type="string" />
<RegistryValue Name="CodeBase" Value="file:///[#filMyAssembly]" Type="string" />
</RegistryKey>
</RegistryKey>
<RegistryValue Root="HKCR" Key="Directory\Background\shellex\ContextMenuHandlers\MyHandler" Value="{guid}" Type="string" Action="write" />
<RegistryValue Root="HKCR" Key="Directory\shellex\ContextMenuHandlers\MyHandler" Value="{guid}" Type="string" Action="write" />
<RegistryValue Root="HKCR" Key="Drive\shellex\ContextMenuHandlers\MyHandler" Value="{guid}" Type="string" Action="write" />
</Component>
The problem I have is with the 32bit version's registration. Because it uses the same assembly I don't want to install the same file twice. All I do is create another (32 bit) component and make the necessary registry changes.
<Component Id="cmp32BitVersion" Directory="INSTALL_TO_32"
Location="local" Win64="no">
<Class ... just like 64bit
<RegistryKey ... just like 64bit
</Component>
Now, I assumed that the Win64 yes/no is how windows installer decides which part of the registry to write to. For 64bit components it writes to HKCR..., for the 32 bit component it would write to HKLM\SOFTWARE\WOW6432Node\Classes. The problem I have is that because both components are using a file reference [#filMyAssembly] I am getting ICE69: Mismatched component reference, warnings. The code still builds but I would prefer not to get the warnings, people who don't heed warnings should expect trouble.
Anyway, my question is: what is the correct way to register a MSIL assembly for COM in both 64 and 32 bit applications using Wix/Windows Installer?
MikeR and nickheppleston at wix-users look like they've found a solution:
http://windows-installer-xml-wix-toolset.687559.n2.nabble.com/64-bit-and-32-bit-Registry-Keys-in-same-MSI-td4439679.html
Thanks all who have responded. I followed MikeR's comments and came up
with the following - I found that I had to reference the x64
Architecture variable when defining both the Component and the
ComponentRef within the Feature section, as follows:
<Component Id="x86LicencingRegistryKeys" Guid="D113AD25-9E80-44E9-80C0-D66828809DBF" Win64="no">
<RegistryKey Id="x86ValidationCodeRegKey" Root="HKLM" Key="SOFTWARE\Product\Licencing" Action="createAndRemoveOnUninstall">
<RegistryValue Id="x86ValidationCodeRegValue" Name="ValidationCode" Action="write" Value="BgIAAACkAABSU0ExgAEAAAEAAQD9iAIysvGIxaJcIiENpOVTZbQosafHa9yXlfG0kxSWKJ01Hlfl+I+4ul5LhxoZkLo=" Type="string" />
<Permission User="Administrators" ChangePermission="yes" GenericAll="yes" />
<Permission User="CREATOR OWNER" ChangePermission="yes" GenericAll="yes" />
<Permission User="Power Users" ChangePermission="yes" GenericAll="yes" />
<Permission User="SYSTEM" ChangePermission="yes" GenericAll="yes" />
<Permission User="Users" ChangePermission="yes" GenericAll="no" GenericRead="yes" />
</RegistryKey>
<RegistryKey Id="x86LicenceKeyRegKey" Root="HKLM" Key="SOFTWARE\Product\Licencing" Action="createAndRemoveOnUninstall">
<RegistryValue Id="x86LicenceKeyRegValue" Name="LicenceKey" Action="write" Value="" Type="string" />
<Permission User="Administrators" ChangePermission="yes" GenericAll="yes" />
<Permission User="CREATOR OWNER" ChangePermission="yes" GenericAll="yes" />
<Permission User="Power Users" ChangePermission="yes" GenericAll="yes" />
<Permission User="SYSTEM" ChangePermission="yes" GenericAll="yes" />
<Permission User="Users" ChangePermission="yes" GenericAll="no" GenericRead="yes" />
</RegistryKey>
</Component>
<?if $(var.Architecture)=x64 ?>
<Component Id="x64LicencingRegistryKeys" Guid="49A15EB4-2DF8-4FF9-83ED-D306F076E232" Win64="yes">
<RegistryKey Id="x64ValidationCodeRegKey" Root="HKLM" Key="SOFTWARE\Product\Licencing" Action="createAndRemoveOnUninstall">
<RegistryValue Id="x64ValidationCodeRegValue" Name="ValidationCode" Action="write" Value="BgIAAACkAABSU0ExgAEAAAEAAQD9iAIysvGIxaJcIiENpOVTZbQosafHa9yXlfG0kxSWKJ01Hlfl+I+4ul5LhxoZkLo=" Type="string" />
<Permission User="Administrators" ChangePermission="yes" GenericAll="yes" />
<Permission User="CREATOR OWNER" ChangePermission="yes" GenericAll="yes" />
<Permission User="Power Users" ChangePermission="yes" GenericAll="yes" />
<Permission User="SYSTEM" ChangePermission="yes" GenericAll="yes" />
<Permission User="Users" ChangePermission="yes" GenericAll="no" GenericRead="yes" />
</RegistryKey>
<RegistryKey Id="x64LicenceKeyRegKey" Root="HKLM" Key="SOFTWARE\Product\Licencing" Action="createAndRemoveOnUninstall">
<RegistryValue Id="x64LicenceKeyRegValue" Name="LicenceKey" Action="write" Value="" Type="string" />
<Permission User="Administrators" ChangePermission="yes" GenericAll="yes" />
<Permission User="CREATOR OWNER" ChangePermission="yes" GenericAll="yes" />
<Permission User="Power Users" ChangePermission="yes" GenericAll="yes" />
<Permission User="SYSTEM" ChangePermission="yes" GenericAll="yes" />
<Permission User="Users" ChangePermission="yes" GenericAll="no" GenericRead="yes" />
</RegistryKey>
</Component>
<?endif ?>
<Feature Id="Complete" Title="TITLE" Description="Complete Package" Display="expand" Level="1" ConfigurableDirectory="INSTALLDIR">
<ComponentRef Id="x86LicencingRegistryKeys" />
<?if $(var.Architecture)=x64 ?><ComponentRef Id="x64LicencingRegistryKeys" /><?endif ?>
</Feature>

wix - shortcut icon for website

I'm new on wix. In need to create a shortcut to a local website.
It works fine and creates the shorcuts, but it doesn't show any icon on start menu and desktop... The website has favicon file and when I open the site I can see it perfectly - I just don't see it in the shortcut. I tried to google it but I didn't find a good answer for util:InternetShortcut..
My code is:
<DirectoryRef Id="ApplicationProgramsFolder">
<Component Id="ApplicationShortcutBBBApp" Guid="---">
<util:InternetShortcut Id="ApplicationStartMenuShortcutBBBApp"
Name="BBB"
Target="http://localhost/BBB"/>
<util:InternetShortcut Id="ApplicationDesktopShortcutBBBApp"
Name="BBB"
Directory="DesktopFolder"
Target="http://localhost/BBB"/>
<RegistryValue Root="HKCU" Key="Software\Microsoft\BBB" Name="installed" Type="integer" Value="1" KeyPath="yes"/>
</Component>
</DirectoryRef>
There is an easier solution for that problem. Instead of using InternetShortcut, you can just use the normal Shortcut and use a trick to set the target being a url.
<SetProperty Id="URL" Value="http://yourpage.com" Sequence="execute" Before="CreateShortcuts" />
<Shortcut Directory="DesktopFolder" Id="WebShortcut" Name="Your Page" Description="Your Page Description" Target="[URL]" Icon="IconDesktop">
<Icon Id="IconDesktop" SourceFile="images\icon.ico" />
</Shortcut>
"SetProperty" can be placed somewhere in your Product tag.
"Shortcut" should be placed instead of "InternetShortcut".
It is important to have the property [URL] as a Target. As a Property it can be an url. Diretctly written it doese not work.
There might be warnings in heat/candle/light, they can be ignored.
InternetShortcut doesn't support specifying an icon like a normal Shortcut. There's an open feature request for that. Technically, IUniformResourceLocator shortcuts in Windows don't support icons, though IShellLink shortcuts do.
A little late answering this, but just needed to do the same thing. The approach I took was to use the iniFile element to write out a url file.
Two points of interest with this approach:
Since the shortcut is on the desktop and the icon file is located elsewhere on the file system, I needed to create separate components to deploy the icon file.
If the MSI is ran as a normal user with UAC turned on, the icon is not set for the shortcut. Once I disabled UAC prior to installing, the icon was set correctly.
<Fragment>
<DirectoryRef Id="DesktopFolder">
<Component Id="ProductInternetShortcut" Guid="{YOUR_GUID_HERE}" >
<IniFile Id="url_name"
Action="addLine"
Directory="DesktopFolder"
Section="InternetShortcut"
Name="ProductInternetShortcut.url"
Key="URL"
Value="https://my.url.com/" />
<IniFile Id="url_target"
Action="addLine"
Directory="DesktopFolder"
Section="InternetShortcut"
Name="ProductInternetShortcut.url"
Key="Target"
Value="https://my.url.com/" />
<IniFile Id="url_idlist"
Action="createLine"
Directory="DesktopFolder"
Section="InternetShortcut"
Name="ProductInternetShortcut.url"
Key="IDList"
Value=" " />
<IniFile Id="url_HotKey"
Action="addLine"
Directory="DesktopFolder"
Section="InternetShortcut"
Name="ProductInternetShortcut.url"
Key="HotKey"
Value="0" />
<IniFile Id="url_icon"
Action="addLine"
Directory="DesktopFolder"
Section="InternetShortcut"
Name="ProductInternetShortcut.url"
Key="IconFile"
Value="PATH_TO_ICON_FILE_ON_WORKSTATION" />
<IniFile Id="url_iconIndex"
Action="addLine"
Directory="DesktopFolder"
Section="InternetShortcut"
Name="ProductInternetShortcut.url"
Key="IconIndex"
Value="0" />
<RegistryValue Root="HKCU" Key="Software\COMPANY\PRODUCT" Name="installed" Type="integer" Value="1" KeyPath="yes" />
</Component>
</DirectoryRef>
<DirectoryRef Id="ProductFolder">
<Component Id="ShortcutIcons" Guid="{YOUR_GUID_HERE}">
<File Id="filProductIcons" KeyPath="yes" Source="PATH_TO_ICON_FILE_ON_DEVELOPER_MACHINE" />
</Component>
</DirectoryRef>
</Fragment>
In Wix you can create an InternetShortcut with an icon via the InternetShortcut Element (Util Extension).
Below is an example from an app I'm working on of adding a link to a website with an icon via the <InternetShorcut> element and placing that link on both the Desktop and the Start Menu.
Note, you may have to put the "util" prefix in front of the element name like so although I didn't have to do that: <util:InternetShortcut>.
<Directory Id="ProgramMenuFolder" Name="ProgramMenuFolder">
<Directory Id="ProgramMenuFolder.MyApplicationName" Name="MyApplicationName">
<Component Id="Component.Uninstall" Guid="215c7bec-7967-43e6-8f01-72c27fbb2a98">
<CreateFolder/>
<RemoveFolder Id="ProgramMenuFolder.MyApplicationName" On="uninstall"/>
<RegistryKey Root="HKCU" Key="Software\MyCompany\MyApplicationName">
<RegistryValue Value="0" Type="string" KeyPath="yes"/>
</RegistryKey>
</Component>
<Component Id="InternetShortcut" Guid="215c7bec-7967-43e6-8f01-72c22e505f09">
<InternetShortcut
IconFile="[INSTALLDIR]\icon.ico"
IconIndex="0"
Name="Admin Page"
Id="InternetShortcut"
Target="http://localhost:4444"
Type="link"
xmlns="http://schemas.microsoft.com/wix/UtilExtension"/>
<CreateFolder/>
<RegistryKey Root="HKCU" Key="Software\MyCompany\MyApplicationName">
<RegistryValue Value="0" Type="string" KeyPath="yes"/>
</RegistryKey>
</Component>
</Directory>
</Directory>
<Directory Id="DesktopFolder" Name="DesktopFolder">
<Component Id="InternetShortcut.1" Guid="B27DF351-6EDA-4BEF-A3AC-F12313260203">
<InternetShortcut
IconFile="[INSTALLDIR]\icon.ico"
IconIndex="0"
Name="Admin Page"
Id="InternetShortcut.1"
Target="http://localhost:4444"
Type="link"
xmlns="http://schemas.microsoft.com/wix/UtilExtension"/>
<CreateFolder/>
<RegistryKey Root="HKCU" Key="Software\MyCompany\MyApplicationName">
<RegistryValue Value="0" Type="string" KeyPath="yes"/>
</RegistryKey>
</Component>
</Directory>
<Feature Id="Complete" Title="Complete" Absent="allow" Level="1">
<ComponentRef Id="InternetShortcut"/>
<ComponentRef Id="InternetShortcut.1"/>
</Feature>
Also, see How To: Create a Shortcut to a Webpage

How can I set an icon for an asscociated file using WiX?

My application install file is being generated using WiX. In the WiX configuration I am associating a file type that works with the application. How can I associate an icon with this file type in the WiX configuration?
FROM: https://www.firegiant.com/wix/tutorial/getting-started/beyond-files/
If your application handles its own file data type, you will need to register a file association for it. Put a ProgId inside your component. FileId should refer to the Id attribute of the File element describing the file meant to handle the files of this extension. Note the exclamation mark: it will return the short path of the file instead of the long one:
<ProgId Id='AcmeFoobar.xyzfile' Description='Acme Foobar data file'>
<Extension Id='xyz' ContentType='application/xyz'>
<Verb Id='open' Sequence='10' Command='Open' Target='[!FileId]' Argument='"%1"' />
</Extension>
</ProgId>
To assign an icon to this file type, you have to specify the appropriate registry entries yourself inside your component:
<Registry Id='FooIcon1' Root='HKCR' Key='.xyz' Action='write'
Type='string' Value='AcmeFoobar.xyzfile' />
<Registry Id='FooIcon2' Root='HKCR' Key='AcmeFoobar.xyzfile' Action='write'
Type='string' Value='Acme Foobar data file' />
<Registry Id='FooIcon3' Root='HKCR' Key='AcmeFoobar.xyzfile\DefaultIcon' Action='write'
Type='string' Value='[INSTALLDIR]Foobar.exe,1' />
This is how I did it. I declared:
<Icon Id="Icon.exe" SourceFile="..\Installer\Graph.ico" />
before </Product> and added it as a reference as follows:
<ProgId Id='myApp.exe' Description='Some description' Advertise='yes' Icon='Icon.exe'>
<Extension Id='xyz' ContentType='application/text'>
<Verb Id='open' Sequence='10' Command='Open' Argument='"%1"' />
</Extension>
</ProgId>
I'd recommend following my stack overflow post located here for the simplest and most elegant way of embedding icons into a resource without the need for a c++ project in a managed .NET application.
Next, here is the proper way to set this via wix:
<Component Id="stackoverflowFileRegistration" Guid="MY_GUID">
<RegistryKey Root="HKCR" Key=".stackoverflow" ForceCreateOnInstall="yes" ForceDeleteOnUninstall="yes">
<RegistryValue Value="stackoverflow.Document" Type="string" KeyPath="yes" />
<RegistryValue Name="Content Type" Value="application/stackoverflow" Type="string" />
<RegistryKey Key="ShellNew" ForceCreateOnInstall="yes" ForceDeleteOnUninstall="yes">
<RegistryValue Name="NullFile" Value="" Type="string" />
<RegistryValue Name="Data" Value="Default new document Content.. NOTE: you must use a MutiStringValue nodes for multi-line content...." Type="string"/>
</RegistryKey>
</RegistryKey>
<RegistryKey Root="HKCR" Key="stackoverflow.Document" ForceCreateOnInstall="yes" ForceDeleteOnUninstall="yes">
<RegistryValue Value="stackoverflow Document" Type="string" />
<RegistryKey Key="DefaultIcon" ForceCreateOnInstall="yes" ForceDeleteOnUninstall="yes">
<RegistryValue Value="[INSTALLDIR]bin\stackoverflow.lib.dll, 1" Type="string" />
</RegistryKey>
<RegistryKey Key="Shell" ForceCreateOnInstall="yes" ForceDeleteOnUninstall="yes">
<RegistryKey Key="openstackoverflowwebsite" ForceCreateOnInstall="yes" ForceDeleteOnUninstall="yes">
<RegistryValue Value="Open Stackoverflow" Type="string" />
<RegistryKey Key="command" ForceCreateOnInstall="yes" ForceDeleteOnUninstall="yes">
<RegistryValue Value=""[INSTALLDIR]stackoverflow.exe" /openwebsite "%1"" Type="string" />
</RegistryKey>
</RegistryKey>
</RegistryKey>
</RegistryKey>
</Component>
This sample registers the default icon for a specific file extension (.stackoverflow) that is located in an assembly from step 1. It also shows how to create Windows Explorer associated right click commands as well as adds a menu item to the Windows Explorer New sub menu.
Thanks
-Blake Niemyjski
Please note that Dracos answer is not suffiecent for a complete icon/file association.
The following code:
This is how I did it. I declared:
<Icon Id="Icon.exe" SourceFile="..\Installer\Graph.ico" />
<ProgId Id='myApp.exe' Description='Some description' Advertise='yes' Icon='Icon.exe'>
<Extension Id='xyz' ContentType='application/text'>
<Verb Id='open' Sequence='10' Command='Open' Argument='"%1"' />
</Extension>
</ProgId>
Is only registering a file/icon association for the dialouges created by the application which is installed by the given wix-project.
To get an icon that is shown overall for all the dialogues, desktop etc. in windows you also need to register your icon for a specific filetype (extension) in regedit.