Issue with registry entry in one .wxs file to create both 32 bit and 64 bit installer - wix3.7

Here is my script:
<DirectoryRef Id="TARGETDIR">
<!--for 64 bit platform-->
<?if $(sys.BUILDARCH)="x64"?>
<Component Id="RegistryEntries64" Guid="EFC1C5ED-0BC8-4B52-943A-BFF5F3136B4F" Win64="yes">
<RegistryKey Root="HKLM" Key="SOFTWARE\ODBC\ODBCINST.INI\ODBC Drivers">
<RegistryValue Type="string" Name="$(var.ProductNameForRegistyEntry)" Value="Installed" KeyPath="yes"/>
</RegistryKey>
<RegistryKey Root="HKLM" Key="SOFTWARE\ODBC\ODBCINST.INI\$(var.ProductNameForRegistyEntry)">
<-------/>
</RegistryKey>
<RemoveFolder Id="RegistryEntries64" On="uninstall"/>
</Component>
<?else?>
<!--for 32 bit platform-->
<Component Id="RegistryEntries86" Guid="E37BE3EF-1979-4C56-A768-2D6B6AB99870" Win64="no">
<RegistryKey Root="HKLM" Key="SOFTWARE\WOW6432Node\ODBC\ODBCINST.INI\ODBC Drivers">
<RegistryValue Type="string" Name="$(var.ProductNameForRegistyEntry)" Value="Installed"/>
</RegistryKey>
<RegistryKey Root="HKLM" Key="SOFTWARE\WOW6432Node\ODBC\ODBCINST.INI\$(var.ProductNameForRegistyEntry)">
<----->
</RegistryKey>
<RemoveFolder Id="RegistryEntries86" On="uninstall"/>
</Component>
<?endif?>
</DirectoryRef>
With this script the 32 bit installer created (x86 platform select in Visual studio 2015) working fine on 64 bit operating system machine, registry entry getting created inside WOW6432Node, basically this is 32 bit installer to install on 64 bit machine, so that user can install both 64 bit and 32 bit installer on 64 bit machine but on 32 bit operating system, registry entry should be inside SOFTWARE\ODBC\ODBCINST.INI\ODBC Drivers. On 32 bit machine Get-OdbcDriver command doesn't returns the driver in the list.
platform variable is not suggested by Wix itself
sys.BUILDARCH fetch the target platform type.
Do I need to write a separate script for 32 bit operating system machine, where I will give registry entry SOFTWARE\ODBC\ODBCINST.INI\ODBC Drivers? Or there some other solution ?
I look so many stackoverflow post and others posts over internet but nothing related to this I could find.
Thanks in Advance

You don't need to create a separate script for that. One possible solution could be you define another variable (i.e Installer_x86_x86) and based on its value you can create 32-bit installer for both 64-bit and 32-bit OS.
<?if $(var.Installer_x86_x86)="no"?>
<RegistryKey Root="HKLM" Key="SOFTWARE\WOW6432Node\ODBC\ODBCINST.INI\ODBC Drivers">
<RegistryValue Type="string" Name="$(var.ProductNameForRegistyEntry)" Value="Installed"/>
</RegistryKey>
<RegistryKey Root="HKLM" Key="SOFTWARE\WOW6432Node\ODBC\ODBCINST.INI\$(var.ProductNameForRegistyEntry)">
<RegistryValue Type="string" Name="Description" Value="TIBCO ComputeDB ODBC Driver" />
</RegistryKey>
<?else?>
<RegistryKey Root="HKLM" Key="SOFTWARE\ODBC\ODBCINST.INI\ODBC Drivers">
<RegistryValue Type="string" Name="$(var.ProductNameForRegistyEntry)" Value="Installed"/>
</RegistryKey>
<RegistryKey Root="HKLM" Key="SOFTWARE\ODBC\ODBCINST.INI\$(var.ProductNameForRegistyEntry)">
<RegistryValue Type="string" Name="Description" Value="TIBCO ComputeDB ODBC Driver" />
</RegistryKey>
<?endif?>
It would be better if you create a .wxi file and put all your variables into it and include it in your .wxs file, so that it will be easy for you change variable value before creating the installer

Related

RubyMine can't trigger docker-compose up in some computers

I have a project configuration in RubyMine to allow running docker-compose up from the toolbar:
The file, .run/docker-compose up.run.xml contains:
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="docker-compose up" type="docker-deploy" factoryName="docker-compose.yml" server-name="Docker">
<deployment type="docker-compose.yml">
<settings>
<option name="envFilePath" value="" />
<option name="sourceFilePath" value="docker-compose.yml" />
</settings>
</deployment>
<method v="2" />
</configuration>
</component>
and it successfully runs on one Windows 10 machine with WSL2 but fails in 2 others with this message:
In all 3 computers running docker-compose up in the WSL2 terminal works. They were all set up by me following roughly the same process, so I'm having trouble finding any differences.
Any ideas what could be going on here?

Multiple Delphi versions using Jenkins: library paths

We are looking at migrating our build machine from FinalBuilder to Jenkins to fit in with the rest of our extended company.
One issue that I have noticed is that whereas Finalbuilder is able to extract the current library path from your current Delphi installs on the build machine, Jenkins relies on the information contained within the .dproj files.
Owing to known problems of the paths within the .dproj files being very specific to a users machine, we don't currently commit them to our repository, relying on Delphi to re-create them as required. This obviously doesn't play nice when the build machine is reliant on a full MSBUILD script being there in the first place.
We use a fair few third-party components (DevExpress suite alone having over 100 units), so including and maintaining all the .pas files with full paths in the .dpr isn't really an option for this.
Does anyone have a tried-and-tested solution for this?
My thoughts on options were:
setting the %PATH% for each build - adding the current Delphi library
for the relevant version (will this run into %PATH% length restrictions?)
Using a command-line parameter to pass the correct library path to MSBUILD (is this possible?)
Including the search path somehow in the source files with compiler directives (is this possible?)
Using a pre-compile step to create new .dproj files (something like http://delphi-divining.blogspot.co.uk/2012/10/dprojmaker-tool-to-create-delphi.html but it'll need to be command-line)
Edit: 5th idea:
Could we use dproj.local files for each project, stored in a separate repository (or in a separate path) and copied to the build machine pre-build? This would allow build machine paths to be stored safely away from clutzy commits.
You need to submit your .dproj file to source control.
You have a problem which is that your configuration is not complete. Any build system should be able to build your project using nothing but files in your source control, that is the ONLY way to ensure you are building the correct binary.
You have a number of options to make this work
You can use Environment variables in the Delphi IDE eg %ROOTFOLDER% could be set to C:\Development\MyDelphiProjects on one machine and C:\Dev on another and as long as everything is the same from that route it should be ok. Each dev and your build machine can set the required path. You may need vars for bpl paths also.
Enforce identical structures on client machines. Really how difficult is it to make all devs us C:\Development\Delphi as their root?
Make sure all search paths are relative. This can work, but there are always exceptions that cause problems so I have never managed to get this to work.
We used option 1 in a previous company and it worked very successfully, its a bit of a pain to set up but once setup you can be sure your build is correct.
I had the same problem when i choose Jenkins as a "build" environment. The solution is to use a MSBuild script with a build task inside. So in Jenkins instead of building the project directly, just build this script which gives you a lot more options, including the option to specify the paths for the project (you can to override the default IDE paths).
I'll post such a script tomorrow.
So in Jenkins when you configure MSBuild you have to specify the msbuild file, which will be Build.xml. For command line arguments i use only /v - verbosity and /t - target name.
The build script looks like this:
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="4.0">
<Target Name="Compile" DependsOnTargets="CompileApp" />
<PropertyGroup>
<ExeOutputName>App.exe</ExeOutputName>
<ExeOutputPath>x:\exe</ExeOutputPath>
<DcuOutputPath>x:\dcu</DcuOutputPath>
<ForConfig>Release</ForConfig>
<ForPlatform>Win32</ForPlatform>
</PropertyGroup>
<Target Name="ResolveOutputPath">
<MakeDir Directories="$(ExeOutputPath)" />
<MakeDir Directories="$(DcuOutputPath)" />
<Delete Files="$(ExeOutputPath)\$(ExeOutputName)" />
<Delete Files="$(DcuOutputPath)\*.*" />
</Target>
<ItemGroup>
<AppUnitSearchPathItem Include="$(BDS)\lib\$(ForPlatform)\$(ForConfig)" />
<AppUnitSearchPathItem Include="C:\Users\builder\Documents\tmssoftware\TMS Component Pack" />
<AppUnitSearchPathItem Include="C:\Program Files (x86)\RemObjects Software\RemObjects SDK for Delphi\Dcu\$(ForPlatform)" />
<AppUnitSearchPathItem Include="C:\Program Files (x86)\RemObjects Software\RemObjects SDK for Delphi\Source" />
<AppUnitSearchPathItem Include="C:\Program Files (x86)\RemObjects Software\RemObjects SDK for Delphi\Source\CodeGen" />
<AppUnitSearchPathItem Include="C:\Program Files (x86)\RemObjects Software\RemObjects SDK for Delphi\Source\DataSnap" />
<AppUnitSearchPathItem Include="C:\Program Files (x86)\RemObjects Software\RemObjects SDK for Delphi\Source\ZLib" />
<AppUnitSearchPathItem Include="C:\Program Files (x86)\RemObjects Software\RemObjects SDK for Delphi\Source\Synapse" />
<AppUnitSearchPathItem Include="C:\Program Files (x86)\Embarcadero\RAD Studio\12.0\Components\EhLib\Lib\$(ForPlatform)\$(ForConfig)" />
...
</ItemGroup>
<ItemGroup>
<AppDefinesItem Include="App" />
<!-- AppDefinesItem Include="CompilerDirective" -->
</ItemGroup>
<ItemGroup>
<AppPropertiesItem Include="DCC_ExeOutput=$(ExeOutputPath)" />
<AppPropertiesItem Include="DCC_DcuOutput=$(DcuOutputPath)" />
<AppPropertiesItem Include="DCC_BuildAllUnits=true" />
<AppPropertiesItem Include="DCC_Optimize=true" />
<AppPropertiesItem Include="DCC_DebugInformation=0" />
<AppPropertiesItem Include="DCC_PentiumSafeDivide=true" />
<AppPropertiesItem Include="DCC_RangeChecking=true" />
<AppPropertiesItem Include="DCC_IntegerOverflowCheck=true" />
<AppPropertiesItem Include="DCC_WriteableConstants=true" />
<AppPropertiesItem Include="DCC_IOChecking=true" />
<AppPropertiesItem Include="DCC_AssertionsAtRuntime=false" />
<AppPropertiesItem Include="DCC_Warnings=true" />
<AppPropertiesItem Include="DCC_MapFile=3" />
<AppPropertiesItem Include="DCC_ConsoleTarget=false" />
</ItemGroup>
<Target Name="CompileApp" DependsOnTargets="ResolveOutputPath">
<PropertyGroup>
<AppUnitSearchPath>#(AppUnitSearchPathItem)</AppUnitSearchPath>
<AppDefines>#(AppDefinesItem)</AppDefines>
</PropertyGroup>
<ItemGroup>
<AppProperties Include="Config=$(ForConfig)" />
<AppProperties Include="Platform=$(ForPlatform)" />
<!-- AppProperties Include="LibraryPath=$(AppUnitSearchPath)" -->
<AppProperties Include="DelphiLibraryPath=$(AppUnitSearchPath)" />
<AppProperties Include="UnitSearchPath=$(AppUnitSearchPath)" />
<AppProperties Include="ResourcePath=$(AppUnitSearchPath)" />
<AppProperties Include="IncludePath=$(AppUnitSearchPath)" />
<AppProperties Include="ObjPath=$(AppUnitSearchPath)" />
<AppProperties Include="DCC_Define=$(AppDefines)" />
<AppProperties Include="#(AppPropertiesItem)" />
</ItemGroup>
<MSBuild Projects="App.dproj" Properties="#(AppProperties)" />
</Target>
</Project>
What is missing here is the versioning part which can be done from this script using a resource template...

Check registry keys of a Software that is already installed in your system For WIX setup

I have a WIX setup. I want to promt message box for some prerequisites before installing my setup.
I am using below code to check registry keys for a particular software.
But it always prompt a message weather a software is installed or not.
<Condition Message="This application requires ReportViewer.">
<![CDATA[ReportViewerV10 OR ReportViewerWow64V10]]>
</Condition>
<util:RegistrySearch
Root="HKLM"
Key="SOFTWARE\Microsoft\ReportViewer\v10.0"
Value="Install"
Variable="ReportViewerV10"
Win64="yes"
/>
<util:RegistrySearch
Root="HKLM"
Key="SOFTWARE\Wow6432Node\Microsoft\ReportViewer\v10.0"
Value="Install"
Variable="ReportViewerWow64V10"
Win64="yes"/>
Can anyone guide me where i am doing wrong?
What should be registry keys for a software?
According to this documentation you don't have your Registry search parameters set up quite right. The following should yield better results.
<Property Id="NReportViewerV10">
<RegistrySearch Id="NetFramework20"
Root="HKLM"
Key="SOFTWARE\Microsoft\ReportViewer\v10.0"
Name="Install"
Type="raw" />
</Property>
<Property Id="ReportViewerWow64V10">
<RegistrySearch Id="NetFramework20"
Root="HKLM"
Key="SOFTWARE\Wow6432Node\Microsoft\ReportViewer\v10.0"
Name="Install"
Type="raw" />
</Property>

Wix 3.8: Installer not uninstalling previous version or installing new version

I have created a Wix installer that is meant to replace an installer that was created in Visual Studio, and is supposed to update a previous version of the software it is installing. I kept the same upgrade code that was used in the previous installer for mine, so I thought that this code would work:
<?xml version="1.0" encoding="utf-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
<Product Id="*"
Name="Product"
Language="1033"
Version="1.0.6.0"
Manufacturer="Company"
UpgradeCode="PREVIOUSLY-USED-UPGRADE-CODE">
<Package InstallerVersion="301"
Compressed="yes"
InstallScope="perMachine"
Manufacturer="Company"
Description="Installs Product"
Keywords="Installer,MSI" />
<Media Id="1"
Cabinet = "Product.cab"
EmbedCab = "yes"/>
<MajorUpgrade Schedule="afterInstallInitialize" DowngradeErrorMessage="A newer version of Product is already installed." AllowDowngrades="no"/>
<Directory Id ="TARGETDIR" Name="SourceDir">
<Directory Id="ProgramFilesFolder">
<Directory Id="CompanyFolder" Name ="Company">
<Directory Id="INSTALLDIR" Name="Product" />
</Directory>
</Directory>
</Directory>
<Feature Id ="ProductFeature"
Title = "Product Feature"
Level = "1">
<ComponentGroupRef Id="ProductComponents"/>
</Feature>
<ComponentGroup Id="ProductComponents" Directory="INSTALLDIR">
<Component Id="cmpCOMAdminW2K" Guid="*">
<File Id="COMAdminW2K" Vital="yes" KeyPath="yes" Name="Interop.COMAdminW2K.dll" Source="Local\Path\To\Interop.COMAdminW2K.dll" />
<!-- Several registry entry updates -->
</Component>
<Component Id="cmpCustomSerializer" Guid="*">
<File Id="CustomSerializer" Vital="yes" KeyPath="yes" Name="AREANAME.Serialization.CustomSerializer.v2.0.dll" Source="Local\Path\To\AREANAME.Serialization.CustomSerializer.v2.0.dll" />
</Component>
<Component Id="cmpProductServer" Guid="*">
<File Id="ProductServer" Vital="yes" KeyPath="yes" Name="AREANAME.ProductServer.Shared.v2.0.dll" Source="Local\Path\To\AREANAME.ProductServer.Shared.v2.0.dll" />
</Component>
<Component Id="cmpRemotingHelper" Guid="*">
<File Id="RemotingHelper" Vital="yes" KeyPath="yes" Name="AREANAME.TechPC.RemotingHelper.v2.0.dll" Source="Local\Path\To\ND1.TechPC.RemotingHelper.v2.0.dll" />
</Component>
<Component Id="cmpProduct" Guid="*">
<File Id="Product" Vital="yes" KeyPath="yes" Name="AREANAME.TechPC.Service.Product.v2.0.exe" Source="Local\Path\To\AREANAME.TechPC.Service.Product.v2.0.exe" />
<ServiceInstall
Id="Product"
Name="ServiceName"
DisplayName="Full Service Name"
Start="auto"
ErrorControl="normal"
Type="ownProcess"/>
<ServiceControl
Id="startAndStopUsrPres"
Name="ServiceName"
Start="install"
Stop="both"
Remove="uninstall"
Wait="yes"/>
</Component>
<Component Id="cmpProductConfig" Guid="*">
<File Id="ProductConfig" Vital="yes" KeyPath="yes" Name="AREANAME.TechPC.Service.Product.v2.0.exe.config" Source="Local\Path\To\AREANAME.TechPC.Service.Product.v2.0.exe.config" />
<RemoveFile Id="RemoveProductConfig" Name="AREANAME.TechPC.Service.Product.v2.0.exe.config" On ="install"/>
</Component>
<Component Id="VersionRegistryEntry" Guid="*">
<RegistryKey Root="HKLM"
Key="Software">
<RegistryKey Key="Company"
ForceCreateOnInstall="yes">
<RegistryKey Key="Product"
ForceCreateOnInstall="yes">
<RegistryValue Id="ProductVersionEntry"
KeyPath ="yes"
Action ="write"
Name="Version"
Value="1.0.6.0"
Type="string"/>
</RegistryKey>
</RegistryKey>
</RegistryKey>
</Component>
</ComponentGroup>
</Product>
</Wix>
*Above code is obviously redacted.
The installer will be run on almost all of my company's machines through a software management system, so I have been testing my installer with the following command line:
msiexec.exe /i <ProductInstaller>.msi /quiet /l*v log.txt
That brings me to the problem. Some of you may have noticed that I have a "RemoveFile" tag inside the component containing my config file. I have it there because that file was not always getting updated when the installer ran. This, coupled with the MajorUpgrade schedule, allowed me to remove that file out of the target directory and ensure that the new config file was always getting put in that location. That fix seemed to work in my tests. The program files all appeared to be correct whenever I tried to run the installer on a machine that had a previous version of the program. However, even with all of the correct files in the correct location, the service would not start, either automatically or by manually attempting to start it within services.msc. Additionally, whenever I tried to run the following to uninstall:
msiexec.exe /x <ProductInstaller>.msi /quiet /l*v log.txt
I received the error message "This action is only available for products that are currently installed."
I'm not sure what to make of that since the new files are where they are supposed to be, and the old files are gone.
With all of that information, my question is somewhat vague: "What am I missing in order to have an installer that puts all files in the proper location and starts the service on install, and stops the service and removes the files on uninstall?"
Any assistance would be appreciated, and I would be happy to provide portions of the log files upon request to anybody who thinks that they would help in helping me to figure out what's going on.
Thank you!
-Seth
It was, in fact, that renamed .dll that was causing the problem.

Wix: Stopping a Windows Service on uninstall

When I uninstall my service I get the error where it says I have to stop such and such service before uninstalling. This is unsatisfactory - the uninstaller should automatically stop it.
I found a blog or newsgroup posting on this months ago and got it to work properly, but now it has stopped working for me. And I don't have a link to the post... maybe someone else know where it is? :) I guess I changed some subtle thing and it stopped working. I find Wix extremely difficult to troubleshoot.
I am using the following include to fetch the property X_ WIN_ SERVICE_ NAME (sorry I don't know how to avoid _ escaping here) from the registry. It doesn't matter on install because in that case I explicitly set it with an input file. This include is used before any components in my wxs file.
<Include xmlns="http://schemas.microsoft.com/wix/2006/wi">
<?ifndef SetupXWinServiceRegistryProperties ?>
<?define SetupXWinServiceRegistryProperties ?>
<?define XWinServiceRegistryKey='Software\X\Y'?>
<Property Id="X_WIN_SERVICE_NAME">
<RegistrySearch Id="XWinServiceNameSearch"
Root="HKLM"
Key="$(var.XWinServiceRegistryKey)"
Name="ServiceName"
Type="raw"/>
</Property>
<?endif?>
</Include>
The following include component is used to save the registry value on install:
<Include xmlns="http://schemas.microsoft.com/wix/2006/wi">
<?ifndef WriteXWinServiceRegistryProperties ?>
<?define WriteXWinServiceRegistryProperties ?>
<Component Id="CompWriteXWinServiceRegistryProps"
Guid="some guid">
<!-- Write properties to the registry. Then they will be
accessable during uninstall. -->
<RegistryValue Root="HKLM"
Key="$(var.XWinServiceRegistryKey)"
Name="ServiceName"
Type="string"
Value="[X_WIN_SERVICE_NAME]"
Action="write" />
</Component>
<?endif?>
</Include>
I have checked my system after install and the registry value is properly written there. The part in my component where the service is setup looks like:
<ServiceInstall Id="ServiceInstallXWinService"
Name="[X_WIN_SERVICE_NAME]"
Start="auto"
DisplayName="xxx"
Description="yyy"
Account="[X_WIN_SERVICE_USER]"
Password="[X_WIN_SERVICE_PASSWORD]"
Type="ownProcess"
ErrorControl="normal"
Vital="yes" />
<ServiceControl Id="ServiceInstallXWinService"
Name="[X_WIN_SERVICE_NAME]"
Stop="both"
Remove="uninstall"
Wait="yes" />
Any ideas?
Are you sure that the X_WIN_SERVICE_NAME property is set to the correct value on uninstall. Use a verbose log file to make sure that the search is setting the value correctly. Everything looks fine (although I don't know why you put everything in Include files instead of just using Fragments).

Resources