How do I determine the full path of the folder that contains 32-bit programs using VBA? It's called "Program Files" on 32-bit Windows systems, but on 64-bit systems it's called "Program Files (x86)".
Environ will do the trick:
debug.print Environ("ProgramFiles")
debug.print Environ("PROGRAMFILES(X86)")
'If you want to check if current PC is x64
debug.print Environ("PROCESSOR_IDENTIFIER")
List of environment variables can be found here.
UPDATE: Based on the conversation I've had with Christian and based on my comments, I looked into this a little more.
I have two machines I tested on:
Machine 1: Win 7 Ultimate, 64 Bit, Office 2010 64 Bit
Machine 2: Win 7 Ultimate, 32 Bit, Office 2007 32 Bit
I ran the following statements in the immediate window:
? Environ("ProgramFiles")
? Environ("PROGRAMFILES(X86)")
? Environ("ProgramW6432")
Results
Machine 1:
C:\Program Files
C:\Program Files (x86)
C:\Program Files
Machine 2:
C:\Program Files
//Blank//
//Blank//
So, based on these limited findings, you may want to see the if ProgramW6432 has a value. If not, assume 32 bit and use ProgramFiles.
IF Environ("ProgramW6432") <> "" THEN
'I'm 64 bit so check both ProgramW6432 and PROGRAMFILES(X86)
ELSE
'I'm 32 bit so check ProgramFiles
END IF
Conversely, you could use PROCESSOR_IDENTIFIER to determine x64 vs. x86 and do the same thing.
I wouldn't say either way is foolproof but should get you on the right track.
One-stop shop
I thought I'd summarize the conclusions that can be drawn from the information scattered across all answers here, plus a bit of integration on my part. Credits to all previous answer posters!
The output of Environ for any given "program file"-related environment variable will vary depending on Windows (32 or 64 bit) as well as Office (32 or 64 bit) as follows:
Windows Office ProgramFiles PROGRAMFILES(X86) ProgramW6432
------- ------ ---------------------- --------------------- ----------------
32-bit 32-bit C:\Program Files [empty string] [empty string]
64-bit 32-bit C:\Program Files (x86) C:\Program Files (x86) C:\Program Files
64-bit 64-bit C:\Program Files C:\Program Files (x86) C:\Program Files
Note that for the Windows 64 bit + Office 32 bit setup, the output of Environ("ProgramFiles") does not match with the actual value of the ProgramFiles environment variable in Windows! At the command prompt, echo %ProgramFiles% returns C:\Program Files, not C:\Program Files (x86).
If you need the path to the 32 bit program files folder (C:\Program Files for 32-bit Windows, and C:\Program Files (x86) for 64-bit Windows) then you can use this function:
Function Get32BitProgramFilesPath() As String
If Environ("ProgramW6432") = "" Then
'32 bit Windows
Get32BitProgramFilesPath = Environ("ProgramFiles")
Else
'64 bit Windows
Get32BitProgramFilesPath = Environ("ProgramFiles(x86)")
End If
End Function
ray023's answer is basically correct, but one addition:
At least on my machine (Win 7 Home Premium 64 bit, Access 2000 installed), both
Environ("ProgramFiles") and
Environ("PROGRAMFILES(X86)")
...return the same folder, C:\Program Files (x86).
To get the "non-x86-folder" (C:\Program Files) on my 64 bit Windows, I need to use Environ("ProgramW6432").
Here's another link about the Environ function, including code how to list all environment variables (that's how I found ProgramW6432).
EDIT:
As I already said in a comment, I just tested it on my other machine as the results seem to depend not only on the operating system, but on the installed MS Office version as well:
This machine runs on Win XP SP3 32-bit, and Access 2000 is installed:
Environ("ProgramFiles") returns C:\Programme.
(that's "Program Files" in German - I'm in Germany and my Windows is in German)
Environ("PROGRAMFILES(X86)") and Environ("ProgramW6432") return an empty string.
--> So the safest way to determine the "x86 folder" (no matter if on Win XP or Win 7) seems to be Environ("ProgramFiles").
Here is an article showing you how to read this information from the registry:
http://accesstips.wordpress.com/2010/01/08/get-a-computers-program-files-folder-path-with-access-vba-and-wmi/
In the comments of that article is also a hint how to retrieve the information from the environment variable "ProgramFiles". But beware, if you have different partitions, there may be more than one "Program Files" folder, for example "C:\Program Files" and "D:\Program Files".
Environ("ProgramFiles") is enough statement for both 32 bit and 64 bit system ... in 64 bit you will get
Result C:\Program Files (x86)
Related
This question already has answers here:
File/DLL installed to {sys} does not appear in C:\Windows\system32
(1 answer)
How to add x86 and x64 VC++ 2019 Redistributables in single Inno Setup installer?
(1 answer)
Closed 11 months ago.
I have an executable (setup.exe) that is being created using inno studio. for the executable to run I have to install a certain dll, which is libusb0.dll. If the system is a 64 bit I have the 64 bit dll being installed inside the system32 folder, also if the application is a 32 bit, it is installed in the syswow64 folder. Now if the system is a 32 bit I have the directory set to install the 32 bit dll in the system32 folder accordingly .
Although there seems to be another case, for example if the system is 64 bit, but the installer is 32bit, will the installer be able to identify that the system is a 64 bit and install it in the correct directory, which would be the syswow64 folder to install the 32bit dlls, or will it still try and install the 32 bit dll into the system32 folder which would be incorrect since its for 64bit dlls on a 64 bit system? In which case the setup will fail to find the correct dll?
I hope this makes sense, it is a little confusing for me, but would be nice to get someone's opinion on it.
The way I have it implemented in inno studio, is that I'm using Check: Is64BitInstallMode so that it checks the system before placing the respective dlls in the system folders.
I need to create a registry key pointing to a file located in the 32 Bit "Program Files" folder that works under both versions (i.e. x86 and x64) of Windows 7 (and higher), even if the accessing process is a 64Bit process in the x64 environment. This folder is:
C:\Program Files in 32Bit Windows
C:\Program Files (x86) in 64 Bit Windows
My problem currently is, that the %programfiles(x86)% variable is not set on 32 Bit windows. So I do not really know which unique variable I can use on both Windows systems to get to the 32 Bit Program Files folder. Any solution to this weird situation?
I have generated a test Plugin using prep2015x64.cmd.
prep2015x64.cmd contents are given below
echo off & setlocal enableextensions enabledelayedexpansion
set _FB_GEN="Visual Studio 14 Win64"
call "%~d0%~p0\common.cmd" %*
if %errorlevel% == 2 exit /b 1
call "%~d0%~p0\winprep.cmd"
The Plugin is completely generated, and to ensure it is 64 bit, I cross checked it with dumpbin /Headers and it gives that DLL is 64 bit
FILE HEADER VALUES
8664 machine (x64)
9 number of sections
56DFCDF9 time date stamp Wed Mar 9 12:47:13 2016
0 file pointer to symbol table
0 number of symbols
F0 size of optional header
2022 characteristics
Executable
Application can handle large (>2GB) addresses
DLL
Then, I try to register it, using an elevated Command Prompt in C:\Windows\SysWOW64.
I use the following command for registration
C:\Windows\SysWOW64> C:\Windows\SysWOW64\regsvr32.exe C:\workspace\firebreath\build\bin\TestPlugin\Release\TestPlugin.dll
It gives me an error:
The Module "C:\workspace\firebreath\build\bin\TestPlugin\Release\TestPlugin.dll"
may not be compatible with version of Windows that you are running.
Check if the module is compatible with an X86(32-bit) or X64(64-bit) version of regsvr32.exe
I am using Windows 7, 64 Bit Operating System, so I am really confused as to what is going wrong here. Is it the plugin generation or something else.
Is there any alternate way to get the Plugin registered.
Thanks in advance.
Most likely the issue is that you're using the 32 bit version of regsvr32; syswow64 stands for "system Windows on Windows 64", in other words it's the 32 bit windows on windows 64 bit. You actually (ironically enough) want to use the c:\windows\system32\regsvr32.exe file.
To be safe, just use the one that is in the path instead of specifying a specific one and you'll always get the right one (unless the computer's configuration was messed up). The 64 bit version will automatically chain to the 32 bit version if it's a 32 bit DLL, but the 32 bit version will just not work if it's a 64 bit dll.
Here's what I did to get it working. I used Visual Studio 2008.
Generated the plugin using fbgen.py
Run the prep2008x64.cmd. Build files and vcproj gets generated in this step.
Open Plugin.vcproj file in any editor and replace /machine:X86 with /machine:X64
Open vcproj and then add "Additional Library Dependencies" with "C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\atlmfc\lib\amd64". This is required for ATL Libraries.
I was not sure of whether it gets linked with 32 bit libraries or 64 bit libraries. So, I explicitly added "Additional Dependencies" in Linker Input with the following below list
"C:\Program Files\Microsoft SDKs\Windows\v6.0A\Lib\x64\Kernel32.lib"
"C:\Program Files\Microsoft SDKs\Windows\v6.0A\Lib\x64\User32.lib"
"C:\Program Files\Microsoft SDKs\Windows\v6.0A\Lib\x64\Gdi32.lib"
"C:\Program Files\Microsoft SDKs\Windows\v6.0A\Lib\x64\WinSpool.lib"
"C:\Program Files\Microsoft SDKs\Windows\v6.0A\Lib\x64\Shell32.lib"
"C:\Program Files\Microsoft SDKs\Windows\v6.0A\Lib\x64\Ole32.lib"
"C:\Program Files\Microsoft SDKs\Windows\v6.0A\Lib\x64\OleAut32.lib"
"C:\Program Files\Microsoft SDKs\Windows\v6.0A\Lib\x64\Uuid.lib"
"C:\Program Files\Microsoft SDKs\Windows\v6.0A\Lib\x64\ComDlg32.lib"
"C:\Program Files\Microsoft SDKs\Windows\v6.0A\Lib\x64\AdvAPI32.lib"
"C:\Program Files\Microsoft SDKs\Windows\v6.0A\Lib\x64\Psapi.lib"
"....\ActiveXCore\Debug\ActiveXCore.lib"
"....\PluginCore\Debug\PluginCore.lib"
"PluginAuto\Debug\PPL_PluginAuto.lib"
"....\NpapiCore\Debug\NpapiCore.lib"
"....\ScriptingCore\Debug\ScriptingCore.lib"
"....\boost\libs\thread\Debug\boost_thread.lib"
"....\boost\libs\system\Debug\boost_system.lib"
"C:\Program Files\Microsoft SDKs\Windows\v6.0A\Lib\x64\WinInet.lib"
Changed the "Target Machine" in Linker Advanced from "Not Set" to "MachineX64(/MACHINE:X64)"
Built the Plugin
Registered the plugin using normal cmd prompt (NOT elevated cmd prompt) and normal regsvr32.exe (NOT specific like C:\Windows\SysWOW64)
C:\Users\Username>regsvr32.exe npPlugin.dll
Tried with Firefox 64 bit version 44.0.2, but it did not work. I thought it was problem with plugin. But no, I later downloaded ChromiumPortable_43.0.2357.18.paf.exe (64 Bit) from https://sourceforge.net/projects/crportable/files/ . Chromium version below 44 only support npapi plugins.
Install the Chromium Portable and enabled npapi plugins in chrome://flags and later launched FBControl.htm. Finally it worked.....!!!
I have an exe which depends on libeay32.dll. Both compiled for 32 bits.
I have copied the exe to C:\Program files (x86)\app\bin and the dll to C:\Program files (x86)\app\lib.
To ensure the correct working, i have added C:\Program files (x86)\app\lib to the path.
On Windows 7 64 bits, when i execute the exe, i got a libeay32.dll not found error.
Using dependency walker for 32 bits, the library is properly located at C:\Program files (x86)\app\lib.
Using sysinternal process explorer the app is executed properly.
Using cmd also works.
Using dependency walker for 64 bits, i can see the missing libraries.
Copying the two files toghether or dll to syswow64 also works perfectly.
If the application was compiled for 32 bits...
Why isnt windows looking for 32 bits libraries?
Why arent the libraries resolved if directory is already on path?
My guess is that w7 is ignoring the path, but according to this:
http://msdn.microsoft.com/en-us/library/ms682586%28v=vs.85%29.aspx
it shouldnt!.
Why i cant run my exe with dependencies located on path?
Should i register the library or something?
Any ideas will be much appreciated.
EDIT:
The program its correctly launched/executed when done from start menu->program, but not directly on the .exe...wtf?
Using procmon seems to be trying to open (note the lack of " "):
"C:\Program Files(x86)\myapp\Third-Party\openssl\LIBEAY32.dll"
but in the path its correct (rechecked: "C:\Program Files (x86)\myapp\Third-Party\openssl")
ANSWER?:
is there a know scenario/bug where setting "C:\Program Files (x86)" on path, lead windows try to load "C:\Program Files(x86)" instead????(see using procmon without ANY filter)
Windows 7 x64 bug?
You can mvoe the lib into the same directory, because there it always checks first. If its found, it is used.
On Windows 64 bit systems you can (not tried) also move the libs to the SystemWOW64 folder where the 32bit versions are stored, but I would recommend the first version.
In x64 bit version of windows, i see that are also x86 bit directories. How do we get that using envirnoment variables ?
List of recognized System Environment Variables in Windows
For, say, Program Files (x86), it's PROGRAMFILES(X86)
Common Files under Program Files (x86) is COMMONPROGRAMFILES(X86)
Which directory are you looking to find, specifically?
PROGRAMFILES(X86) refers to the C:\Program Files (x86) folder on 64-bit systems.
See here: http://technet.microsoft.com/en-us/library/dd560744(WS.10).aspx