Name of shortcut created by wix installer to support latin as well as Russian,Japanese and Korean strings - wix

I need to create an installer using wix which would create a shortcut entry. The name of this shortcut would vary with the language property specified by user while installing.
Now I have taken the approach of replicating the component tag for different languages.
Product Codepage is 1252.
<Component Id='XYZAppShortcutFr' Guid='XXXXXX'>
<Condition>LANGUAGE="fr"</Condition>
<Shortcut Id='ShortcutFr' Name='Démarrer $(var.ShortcutName)' Target='[INSTALLDIR]$(var.TargetEXE)' WorkingDirectory='INSTALLDIR' >
</Shortcut>
</Component>
<Component Id='XYZAppShortcutFr' Guid='XXXXXX'>
<Condition>LANGUAGE="ru"</Condition>
<Shortcut Id='ShortcutFr' Name='начало$(var.ShortcutName)' Target='[INSTALLDIR]$(var.TargetEXE)' WorkingDirectory='INSTALLDIR' >
</Shortcut>
</Component>
It fails with error:A string was provided with characters that are not available in the specified database code page.
How do I make my installer generic to support latin languages along with korean/Japanese..?

The right way how to do it should be by transforms... basically you need to make couple of installations.... for each language one, then make transform files... and then you will probably need to make an bootstraper (burn) and apply right transform to installer...
More here: http://wix.tramontana.co.hu/tutorial/transforms/morphing-installers

Related

Burn: Pass RegistrySearch results value to Custom Bootstrapper

In my Bundle code, I'm trying to use the result of a registry search to set Variable to be used in my Custom Boostrapper:
<util:RegistrySearch
Id="ThirdPartyInstallDirSearch"
Variable="THIRDPARTY_INSTALL_DIR"
Root="HKLM"
Key="SYSTEM\CurrentControlSet\Control\Session Manager\Environment"
Value="OceanSoftDir"
Result="exists"
/>
<Variable Name="THIRDPARTY_INSTALL_DIR" Type="string" Value="$(var.THIRDPARTY_INSTALL_DIR)"/>
But this would give an error:
Undefined preprocessor variable '$(var.THIRDPARTY_INSTALL_DIR)'
Basically, I want to pass the result of registry search to my custom bootstrapper application.
Thanks
As the error says, $(var.<NAME>) is a preprocessor define from either a wxi file or from the project file <DefineConstants>name=value</DefineConstants> or from a <?define?>. You can read more about the preprocessor here.
For your issue, the registry search itself should be defining the variable. I do something similar to what you want in a bootstrapper.
<Fragment>
<util:RegistrySearch
Id="ClientInstalledCheck"
Root="HKLM"
Key="SOFTWARE\Client"
Value="ClientPath"
Result="value"
Variable="ClientInstalled"/>
<util:DirectorySearch
Path='[ClientInstalled]'
Variable='InstallFolder'
After='ClientInstalledCheck'
Condition='ClientInstalled' />
</Fragment>
And then in the products installed by the bootstrapper I will pass in the "InstallFolder" value to these installs.
<MsiProperty Name="INSTALLDIR" Value="[InstallFolder]"/>
This way if the user has installed in a non-default install location, we pick up the custom location they chose and use that instead. If the registry key did not exist, we use the default location.
I also have the InstallFolder variable defined with a default location (since my use case is slightly different than yours) as
<Variable Name="InstallFolder" Type="string" Value="[ProgramFilesFolder]$(var.CompanyInstallDir)\" bal:Overridable="yes" Persisted="yes"/>
Where CompanyInstallDir is defined as a preprocessor variable through <DefineConstants> which is originally defined somewhere in an MSBuild properties file.
So to explain your issue, you are mixing preprocessor directives and Variables. In your registry search, you're using Result="exists" which will set the variable THIRDPARTY_INSTALL_DIR to '0' or '1'. You want to use Result="value". This will put the registry location's value in the variable you define in the Variable="" attribute.
If you do the registry search + directory search with condition, you can properly set a variable if and only if the registry exists AND the directory is actually present on the machine and properly handle cases where it isn't but the registry still exists.
Some things you may do differently since the use case is slightly different but hopefully this sets you on the right path for doing what you need to do.

PYRO0243 while building patch

I had the following "Reg2015" component in RTM in which I forgot to assign KeyPath:
<DirectoryRef Id="INSTALLLOCATION">
<Component Id="Reg2015" Guid="{xxx}" Win64="no" >
<RegistryKey Root="HKLM" Key="SOFTWARE\Mine" >
<RegistryValue Name="RefCount" Value="1" Type="integer" />
<RegistryValue Name="Name" Value="Mine" Type="string" Action="write" />
</RegistryKey>
</Component>
...
</DirectoryRef>
To prepare the patch, I changed "RefCount" to "2" and added to patch wxs.
Now PYRO.EXE complains like this:
error PYRO0243: Component 'Reg2015' has a changed keypath in the transform 'C:\Patch\Patch.Wixmst'. Patches cannot change the keypath of a component.
error PYRO0260: Product '{xxx}': Table 'CreateFolder' has a new row 'INSTALLLOCATION/Reg2015' added. This makes the patch not uninstallable.
I understand since there was no "KeyPath", its KeyPath defaulted to INSTALLLOCATION, but didn't know that component ID was considered as a directory.
(1) Can someone explain why?
(2) Is there any way to pass PYRO errors?
(3) For my next major release, if I add "KeyPath" to any of "RegistryValue" element, like
<RegistryValue Name="RefCount" Value="1" Type="integer" KeyPath="yes" />
should I be able to change "RefCount" to 2 in the future patch?
Thanks.
I think WiX selected Refcount as the keypath for the component - that's what the docs say. " If KeyPath is not set to 'yes' for the Component or for a child Registry value or File, WiX will look at the child elements under the Component in sequential order and try to automatically select one of them as a key path. Allowing WiX to automatically select a key path can be dangerous because adding or removing child elements under the Component can inadvertantly cause the key path to change, which can lead to installation problems. " You could verify that by looking in the MSI file with Orca to see what the Component table says about it.
So changing the keypath value probably resulted in that issue. It would be better to set another registry item (or create a new one) in the component to be the keypath.

WiX: Does setting MultiInstance attribute to yes generate unique component IDs for each instance transform, even when static guids are used?

I have two msi packages that gets triggered by a bootstrapper and together install a product. I have multiple instance transforms defined for each msi, and I want to set the MultiInstance attribute to 'yes' for all the components in the harvested fragment such that a new component GUID will be generated per instance transform. (It seems that for now, there isn't a heat parameter that you can set to do this, and it has to be accomplished via an xslt transformation.)
I'd want to use -gg flag for Heat to auto-generate static GUIDs because the install directory is set during run-time as a parameter and is not necessarily a standard directory.
Basically, the output should look like:
<Fragment>
<DirectoryRef Id="TARGETDIR">
<Component Id="cmp32EAD7F5A154CBFA668F294AEEE77B45" Guid="{6529235A-EE06-47EB-A56B-1D016B2396CF}" MultiInstance="yes" >
<File Id="fil3F2F6C0F947339E1ED2CF4459569CC5A" KeyPath="yes" Source="$(var.BIN)\File1.txt" />
</Component>
</DirectoryRef>
... Etc.
I'm wondering, even if the GUID is hard-coded such that the linker does not generate it (like above, instead of Guid="*"), will the MultiInstance attribute being set to 'yes' generate unique guids for each instance transforms' components? I sot of became confused about this when I was test calling the MsiGetProductCode by passing in a component guid for a file, which was defined like below:
<Component Id="ProductComponent" Guid="{1C149757-1E1D-424D-AF77-A156CB87F0BF}" MultiInstance="yes">
<!-- TODO: Insert files, registry keys, and other resources here. -->
<File Id="Picture1" Source="C:\Users\Public\Pictures\Sample Pictures\Desert.jpg" ProcessorArchitecture="x64" />
</Component>
* This is a test file that gets installed for all instance transforms defined.
I had two instances from the msi installed (Instance1, Instance2) and the MsiGetProductCode function ran as a part of a custom action that executes during uninstall. On the first execution of MsiGetProductCode, I got the ProductCode of Instance1. On the second execution of MsiGetProductCode (after Instance1 was removed), I got the ProductCode of Instance2. It seemed like that static component id had been used for both instance transforms.
Is the unique component ID generated by the MultiInstance attribute being set to 'yes' not supposed to replace that visible component guid? I haven't had any issues certain files or registry values not being removed due to a component still being used. Basically, I want to confirm that unique guids are being generated per instance and that it's safe to use the MultiInstance attribute to guarantee that component ID collisions will not occur, even when static guids are in use. Could someone kindly elaborate how this works in the background?
Thanks a lot in advance!
It's pretty easy to confirm WiX behavior just by logging the install. Consider the following code:
<Component Id="test" Guid="{EAF11690-2396-4EBE-A74D-37FA1751BBC3}" MultiInstance="yes">
<File Id="test" Source="C:\windows\notepad.exe" KeyPath="yes" />
</Component>
<InstanceTransforms Property="INSTANCEID">
<Instance Id="I01" ProductCode="{7474D99A-B56C-4767-B437-52F56746274A}" ProductName="ProductName2-1" UpgradeCode="{7C2BE622-7543-4F22-A0ED-A9FD28C78C8A}"/>
</InstanceTransforms>
Logging the base and secondary installation reveals that the GUID is unique / transformed.
Another thought would be to extract the instance transform from the MSI and apply it using ORCA to see the differences.
MSI (s) (E4:A4) [10:36:37:021]: Executing op:
ComponentRegister(ComponentId={EAF11690-2396-4EBE-A74D-37FA1751BBC3},KeyPath=C:\Program
Files
(x86)\MyCompany\ProductName2\notepad.exe,State=3,,Disk=1,SharedDllRefCount=0,BinaryType=0)
MSI (s) (E4:DC) [10:37:04:234]: Executing op:
ComponentRegister(ComponentId={BEC4E6A5-9CFB-5C77-A854-CC0179CFEDCE},KeyPath=C:\Program
Files (x86)\My
Company\ProductName2\notepad.exe,State=3,,Disk=1,SharedDllRefCount=0,BinaryType=0)

How to write a Feature state to a registry key

What is the best way to write, to a reg key, if a feature was installed during setup?
You should use Component with condition speified. Condition may reference feature states (current or requested - for more details see this link). I use '&' symbol - it gets requested (which should be achieved with installation) feature state.
<Component Id="MyComponentSpecificReg" Guid="YOURGUID">
<Condition>&MyFeatureId = 3</Condition> <!--install this component only of feature requested state is LOCAL (You may need other condition - please read the link I posted above)-->
<RegistryKey Root="YOUR REG ROOT" Key="YOUR REGISTRY PATH" Action="create">
<RegistryValue Name="YourKeyName" Type="string" Value="[YOUR_PROPERTY]"/>
</RegistryKey>
</Component>

Working example of WIX script that registers help in MS Help 2.0 needed

Can anybody give an example of WIX script to register custom help in visual studio help? I,ve searched for some tutorial, but the only thing that I found was VS schema reference. Everything I tried to do did not work. I use WIX 3.0.
I hope this answer is not too late.
You're going to need:
Your help collection (and some details, such as the internal collection name).
Orca
Some merge modules included as part of the Visual Studio SDK
First thing you want to do is create the Wix code that will hold your help collection.
<DirectoryRef Id="MyHelpDirectory">
<Component Id="MyHelpCollection" Guid="INSERT_GUID_HERE">
<File Id="MyHelpCollection.HxS" Source="..\MyHelpCollection.HxS" KeyPath="yes" />
<File Id="MyHelpCollection.HxA" Source="..\MyHelpCollection.HxA" />
<File Id="MyHelpCollection.HxC" Source="..\MyHelpCollection.HxC" />
<File Id="MyHelpCollection.HxT" Source="..\MyHelpCollection.HxT" />
<File Id="MyHelpCollectionFIndex.HxK" Source="..\MyHelpCollectionFIndex.HxK" />
<File Id="MyHelpCollectionIndex.HxK" Source="..\MyHelpCollectionIndex.HxK" />
<File Id="MyHelpCollectionKIndex.HxK" Source="..\MyHelpCollectionKIndex.HxK" />
<File Id="MyHelpCollectionNamedUrlIndex.HxK" Source="..\MyHelpCollectionNamedUrlIndex.HxK" />
</Component>
</DirectoryRef>
Next, you want to make a copy of the MSHelp2_RegTables_RTL_---_---.msm merge module. (It can be found at C:\Program Files\Microsoft Visual Studio 2008 SDK\HelpIntegrationWizard\MSHelp2) and open it with Orca.
Here you want to edit the HelpNamespace table in the merge module. You're going to want to fill a record with the following information:
NamespaceKey = Company.MyHelp.1033 (You can get this from the person who created your help collection.)
NamespaceName = Company.MyHelp.1033
File_Collection = MyHelpCollection.HxC (Note that this is the Id attribute of the HxC file declared in the Wix code above.)
Description = My Help Collection
Now you want to edit the HelpFile table:
HelpFileKey = MyHelp (Taken from the NamespaceKey above.)
HelpFileName = MyHelp
LangID = 1033
File_HxS = MyHelpCollection.HxS (Note that this is the Id attribute of the HxS file declared in the Wix code above.)
File_HxI = MyHelpCollection.HxI (This is the Id attribute of the HxI file if your collection uses an HxI file. The collections I use do not use HxI files.)
File_HxQ = N/A
File_HxR = N/A
File_Samples = N/A
Next you want to edit the HelpFileToNamespace table:
HelpFile = MyHelp (Note that this must match the value defined in the HelpFile table above.)
HelpNamespace = Company.MyHelp.1033 (Note that this must match the value defined in the HelpNamespace table above.)
Finally, you want to edit the HelpPlugin table:
HelpNamespace_ = Company.MyHelp.1033 (Once again, keep this consistent)
HelpNamespace_Parent = MS_VSIPCC_v80 (For VS2005)
= MS.VSIPCC.v90 (For VS2008)
File_HxT = MyHelpCollection.HxT (Id attribute for HxT file from Wix)
File_HxA = MyHelpCollection.HxA (Id attribute for HxA file from Wix)
File_ParentHxT = FL_vsipcc_hxt_86880________.3643236F_FC70_11D3_A536_0090278A1BB8 (For VS2005)
= FL_vsipcc_hxt_86880_86880_cn_ln.3643236F_FC70_11D3_A536_0090278A1BB8.48273237_1399_45CF_801C_338E1AB00E90 (For VS2008)
You can now save your copy of the MSHelp2_RegTables_RTL_---_---.msm merge module. It's probably a good idea to rename it to something like MyHelpCollection.msm.
Now you just have to include this merge module in your wix project, in addition to the VSIP merge module for the version of VS you're targeting:
<Merge Id="MyHelpCollectionMerge"
Language="1033"
Disk="1"
SourceFile="PATH_TO_THE\MyHelpCollection.msm" />
<!-- For VS2005 -->
<Merge Id="VS2005VSIPMerge"
Language="1033"
Disk="1"
SourceFile="C:\Program Files\Microsoft Visual Studio 2008 SDK\HelpIntegrationWizard\VS_2005\VSIPCC_Collection_Files_RTL_---_---.msm" />
<!-- For VS2008 -->
<Merge Id="VS2008VSIPMerge"
Language="1033"
Disk="1"
SourceFile="C:\Program Files\Microsoft Visual Studio 2008 SDK\HelpIntegrationWizard\VS_2008\VSIPCC_Collection_Files_RTL_---_---.msm" />
Adapted from MSDN Walkthrough