Can I set up a 64-bit registry key to refer to a 32-bit program files path using WiX?
I'm writing a plugin for another piece of software. I want my plugin dll to go in C:\Program Files (x86)\MyPlugin\MyPlugin.dll not in C:\Program Files\MyPlugin\MyPlugin.dll because the dll is 32-bit, not 64-bit.
However, I need the registry key to go in HKLM/Software/Company/Product/Etc.... not in HKLM/Wow6432Node/Software/Company/Product/Etc.... because the process that actually reads the registry key is 64-bit. That 64-bit process reads the registry and launches a 32-bit process to sandbox the dll.
Is there any way to do this? I've tried using different components with different Win64 attribute values, and even putting them in separate component groups. However, I keep getting these build errors (not warnings):
ICE80: This 64BitComponent RegistryComponent uses 32BitDirectory INSTALLFOLDER
A somewhat poor solution, but you could just a custom action to add registry entries, if you don't mind them sticking around after an uninstall.
If you write a custom action in C# you can just do something like this:
using (var hklm = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry64))
{
// do it
}
If you support 32-bit and 64-bit machines you need two separate MSI setups:
http://blogs.msdn.com/b/heaths/archive/2008/01/15/different-packages-are-required-for-different-processor-architectures.aspx
So your 32-bit install creates any COM entries for any 32-bit Clients and the 64-bit setup has 32-bit and 64-bit components that write to the registry.
http://msdn.microsoft.com/en-us/library/aa367451(v=vs.85).aspx
A rather easy solution to only have one installer version for 32 and 64 bit is to export a .reg file with the keys you want to add (from regedit) and then run a custom action during install, ie:
<CustomAction Id='Add_Registry_Keys' Execute='deferred' Directory='DriverDir' Impersonate='no' ExeCommand='regedit.exe /s "[DriverDir]default.reg' Return='ignore' />
You can suppress ICE errors also, not just warnings. This means you can use Win64 attributes in your x86 msi.
The setting to ignore ICE validations is found in the Project Properties under the Tool Settings tab.
It might not be recommended, but if it works its still better than the alternative of a custom action.
Related
I have a batch file that copies a directory to a new location, creates 2 other .bat files, 2 .json files, and Inserts Registry Keys. When running the batch script for the command line, I get no errors and all desired outcomes. While running it from the post-build event command-line, I get no errors, but I'm missing the Registry entries. Co-worker suggested that this could be due to Visual Studio not having Admin permissions whereas the command line can. My question is: is there a way (without running Visual Studio as an admin) to elevate permissions for a post-build event? If you're wondering why not just run VS as admin, it's because this solution is shared via TFS, and not all my co-workers will know to run their instance of VS as admin for this one particular solution. I've Googled away with nothing to show for it. Thanks in advance for help! Here's the Post-build event command line I'm using. Again I know it works... it just doesn't plop the Registry values. CMD does. PS. Using VS 2013 on Windows 7
if $(ConfigurationName) == Debug call "$(ProjectDir)BatchFiles\DebugHelper.bat" "$(TargetDir)" C:\CEC\Batch\Test\
This is from Windows SDK about redirection (there is also reflected and shared)
Registry Redirector
The registry redirector isolates 32-bit and 64-bit applications by providing separate logical views of key portions of the registry on WOW64. The registry redirector intercepts 32-bit registry calls to each logical registry view and maps them to the corresponding physical registry location. The redirection process is transparent to the application. Therefore, a 32-bit application can access registry data as if it were running on 32-bit Windows even if the data is stored in a different location on 64-bit Windows.
Redirection is enabled for the following registry keys:
HKEY_LOCAL_MACHINE\Software
HKEY_USERS\*\Software\Classes
HKEY_USERS\*_Classes
Note * indicates a match for all user security IDs (SID).
The following scenario illustrates the use of these logical views:
A 32-bit application checks for the existance of the following registry key: HKEY_LOCAL_MACHINE\Software\Hello. If the key does not exist, it creates it with a default value of "Hello 32-bit world"; otherwise, it reads and displays the value.
The same application is modified to write "Hello 64-bit world" instead of "Hello 32-bit world" and recompiled as a 64-bit application.
When the 32-bit application is run on 64-bit Windows, it displays "Hello 32-bit world". When the 64-bit application is run, it displays "Hello 64-bit world". Both applications call the same registry functions with the same predefined handle and the same key name; the difference is that each application operates on its logical view of registry, and each view is mapped to a separate physical location of the registry, which keeps both versions of the string intact.
To help applications that write REG_EXPAND_SZ keys containing %ProgramFiles% to the registry, WOW64 intercepts these writes and replaces them with "%ProgramFiles(x86)%". This environment variable is defined for all processes. For example, if the Program Files directory is on the C drive, then "%ProgramFiles(x86)%" expands to "C:\Program Files (x86)".
To enable application interoperability through COM and other mechanisms, WOW64 uses registry reflection, which copies specific registry keys and values between the two registry views to keep them in synch. The reflector is intelligent and copies COM activation data for Local servers between the views, but not in-process data, because 32/64 in-process data mixing is not permitted on 64-bit Windows.
What to do
In a program
KEY_WOW64_64KEY 0x0100 Access a 64-bit key from either a 32-bit or 64-bit application.
Windows 2000: This flag is not supported.
KEY_WOW64_32KEY 0x0200 Access a 32-bit key from either a 32-bit or 64-bit application.
Windows 2000: This flag is not supported.
From command prompt see reg flags /? allowing your key to opt out of redirection.
And a reminder that UAC also may be virtualising it. As it redirects some writes to HKLM to HKCU. Giving permission for users to write to your key will overcome that.
Forgive me if the title is not so accurate.
I have met some problem when I am doing something related to COM server and registry redirection and not quite sure is my understanding is correct or not. Hoping anyone could share some light on it. Thanks in advance.
Basically a COM server has been registered in the registry before anyone can use its service. On a 64bit Windows OS, there could be 2 possible views in the registry table, one is for default and the other for the WOW64 view. For example, first registry key is: COMPUTER\HKEY_LOCAL_MACHINE\SOFTWARE\Classes\CLSID{GUID}\LocalServer32 and the other is: COMPUTER\HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Classes\CLSID{GUID}\LocalServer32.
And depends on the process bitness (64bit vs. 32bit) that either one can be read by default, and also we can use KEY_WOW64_64KEY or KEY_WOW64_32KEY (as: http://msdn.microsoft.com/en-us/library/windows/desktop/aa384129(v=vs.85).aspx) to access the other alternative registry key.
What I need is that, I want to get the LocalServer32 executable file by reading the registry key and this can work. The problem is that, for the executable file path I read back, do I need to do the file path translation (in order to get the correct value) depending on which view I get the value from? For example, if the file path is got from COMPUTER\HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Classes\CLSID{GUID}\LocalServer32 and the file path is: C:\Windows\System32\abc.exe, do I need to translate the path to: C:\Windows\SysWow64\abc.exe? Or do I need to translate C:\Program Files\abc.exe to C:\Program Files(x86).exe?
Another question is that, if, for some registry key for COM, the values set in the two Views are different (for example, one has C:\Program Files\abc.exe and the other has C:\Program Files(x86)\abc.exe), then when the COM server is started, how could svchost.exe know which one to start, C:\Program Files\abc.exe or C:\Program Files(x86)\abc.exe? Does anyone know the logic for svchost.exe to determine this? Use the first one if it exists otherwise use the second one?
Thanks a lot.
A 64-bit version of Windows already has all the features in place to make it unnecessary for you to take care of it yourself. You just need to keep the rules in mind when you troubleshoot problems.
First is the registry redirector, it ensures that a 32-bit client program cannot accidentally read keys that contain configuration information that's only appropriate for 64-bit programs. You already know it, most of the HKLM\Software registry accesses are redirected to HKLM\Software\Wow6432Node. This redirection is already in place when the COM server is registered, a 32-bit installer is automatically redirected to write the keys to Wow6432Node instead. The installer is completely unaware that Wow6432Node even exists. Everything falls together automatically, the installer is redirected and the COM server client is redirected as well. All that you care about is knowing where to look to verify that the install was done properly, you do have to look at HKLM\Software\Wow6432Node\Classes\CLSID with Regedit.exe to find the keys back.
File redirection works much the same way, any access to c:\windows\system32 is redirected to c:\windows\syswow64, from c:\program files to c:\program files (x86). And very similarly, a 32-bit installer doesn't have to know beans about this, it can simply use the legacy 32-bit path names. Same for any 32-bit client program, it will be redirected the same way. All that you care about is knowing where to look for a file to verify the installer.
This can only go wrong if bitness is mixed, a 64-bit program reading registry keys or files installed by a 32-bit program. Or the other way around. Like it does with your troubleshooting tools, like Explorer, Regedit and SysInternals' Process Monitor. In general something that should be strongly avoided in COM, most servers are in-process servers and running 32-bit code in a 64-bit process is not possible. The biggest reason that the registry and file redirectors exist in the first place.
We currently have a 32bit application that requires various key/value pairs to be loaded from the registry before use.
Previously we had completed this by loading the .reg as part of the installation. Running it on 64-bit Windows the .reg components end up in the 64-bit store, but our 32-bit application looks in the 32-bit store.
I was thinking of using KEY_WOW64_64KEY to force our 32-bit application to always use the 64-bit store however this answer advises against that. Then I thought we could change the .reg file to point to the 32-bit store but the comment on this answer advises against assuming the key will always be called "Wow6432Node"
Is there any perferred way to do this (other than migrating the whole app to 64-bit)? What are risks of a 32-bit application using the 64-bit store?
As long as you don't pass the HKEY handle to non Reg* functions that expect x86==native registry I don't think there are any risks. (Filesystem redirection on the other hand is not per handle and can cause problems if a sub-function calls LoadLibrary or CoCreateInstance etc)
If using KEY_WOW64_64KEY seems like too much of a hack, why not have the (32 bit) installer write to the registry instead of using .reg files? The only downside by doing this is that if you create a x64 version of your app in the future it will not share the settings with the x86 version. (This might be a good thing or a bad thing)
Just out of curiosity, if I am creating a program installer, how should I decide in which "Program Files" directory to install to? On 32-bit systems, the environmental variable "%programfiles%" is good enough. However, on 64-bit systems, 32-bit programs should not install to that folder and instead to "%programfiles(x86)%", which as I understand points to "C:\Program Files (x86)". My question is: How should the installer decide which environment variable to use? Will the value of "%programfiles%" change for a 32-bit application, or should I always check first whether "%programfiles(x86)%" exists before using "%programfiles%", or should I do something entirely different?
Thanks! This is just out of my own curiosity, as I try to get used to 64-bit operating systems.
When the 32-bit program (installer in your case) asks the system to resolve the ProgramFilePath constant (check the exact name in MSDN), the system does not return C:\Program files, but C:\Program files(x86). So it's the system that decides, not the application.
I'm pretty certain that I read somewhere that Windows did this for you automagically. In other words, if your installer was 32-bits, it would be routed to the x86 directory variant even though you were trying to install into Program Files.
I'm sure I read this on The Old New Thing but here's a link that supports the contention until I can find that one.
Ah, yes, here it is, from the ever useful Raymond Chen.
Commenter Koro is writing an installer in the form of a 32-bit program that detects that it's running on a 64-bit system and wants to copy files (and presumably set registry entries and do other installery things) into the 64-bit directories, but the emulation layer redirects the operations into the 32-bit locations. The question is "What is the way of finding the x64 Program Files directory from a 32-bit application?"
The answer is "It is better to work with the system than against it." If you're a 32-bit program, then you're going to be fighting against the emulator each time you try to interact with the outside world. Instead, just recompile your installer as a 64-bit program. Have the 32-bit installer detect that it's running on a 64-bit system and launch the 64-bit installer instead. The 64-bit installer will not run in the 32-bit emulation layer, so when it tries to copy a file or update a registry key, it will see the real 64-bit file system and the real 64-bit registry.
We have an application which, for various reasons, needs to be compiled as both a 32-bit and 64-bit app. The thing is, we want to distribute both setup files (msi) on a single CD. Is there a launch condition or autorun.inf entry that we can use to know which setup.exe to launch? Or do we need to write a separate little exe that gets called by autorun, and which determines the OS, and calls the appropriate setup.exe?
There does not appear to be any 32/64bit detection support inherent in autorun.inf files.
The convention that most applications which supply a 32 and 64 bit MSI follow is similar to the second option you mention.
Create a single 32bit setup.exe application (so that it will run on either platform). Ideally this will be written in C/C++ so that it is as small and quick as possible, and has no dependencies on other libraries/frameworks (eg. static linked).
Detect if you are running on 64bit or not (see sample code for Windows API IsWow64Process function
Execute the appropriate MSI
You can use a custom action to detect the OS, then call the right installer.
I've given an example here: Single MSI to install correct 32 or 64 bit c# application