Resolve PROGRAMFILES variable from 32bit app in Win64 OS? - delphi

As explained in MSDN's WOW64 Implementation Details, the variable %PROGRAMFILES%,
in a 32-bit-process on a 64-bit-Windows OS, resolves to C:\Program Files (x86)
in a 64-bit-process on a 64-bit-Windows OS, resolves to C:\Program Files
You can verify this e.g. with a Delphi 10.1 program, compiled both with the 32-bit Windows Target Platform and with the 64-bit Windows Target Platform:
MyShellExecute('%PROGRAMFILES%');
So, from a 32-bit Delphi Application executed in a Windows-64bit-OS, how can I get BOTH:
the ProgramFiles directory for 32-bit-Programs (C:\Program Files (x86))
the ProgramFiles directory for 64-bit-Programs (C:\Program Files)

Use the following environment variables:
ProgramW6432 to obtain the 64 bit program files directory.
ProgramFiles(x86) to obtain the 32 bit program files directory.
These return the same values in both 32 and 64 bit processes.
Of course, relying on environment variables is always a little brittle. It's always possible for your parent process to have modified these variables before creating your process.
To make your program more robust you should use known folder IDs instead. Use FOLDERID_ProgramFilesX64 and FOLDERID_ProgramFilesX86.

Related

Delphi compile error F2048 Bad unit format

I ran into an obscure error and am posting the solution here in the hope that it will help someone else having the same problem.
I am writing a Continuous Integration (CI) program using Delphi XE4 to ensure that a set of pascal source files will compile under older versions of Delphi. This CI program runs a series of batch files each running the command line compiler of an older Delphi version. The batch file running the XE compiler produced the following error:
F2048 Bad unit format: 'c:\program files (x86)\embarcadero\rad studio\11.0\lib\Win32\release\System.dcu' - Expected version: 22.0 ... Found version: 25.0
Note that the expected and found versions are different (in this case XE and XE4). Several people have reported similar errors where the expected and found versions were the same - this is usually a mixup between 32 and 64 bit DCUs, but that wasn't the problem here.
This problem only occurs when the CI program is run from within the Delphi XE4 IDE. If the CI program is run outside of the IDE it works fine.
The XE4 IDE adds several environment variables that are inherited by the program being debugged (in this case CI) that are in turn inherited by the batch files. One of these extra environment variables confuses the XE compiler when run in the batch file. The culprit is the added BDSLIB environment variable that points to the XE4 lib directory.
The solution was to simply add
set BDSLIB=
to the beginning of each of batch files. Once this change was made the CI program runs successfully both inside and outside the IDE.

Copying System32 DLL using MSYS breaks the 64bit being of the library

Under Windows 7 64bit, the *32.dll from System32 are 64bit libraries (according to Dependency Walker - depends.exe x64). A strange issue I noticed is that doing - for example - cp /c/System32/ws2_32.dll /c/mingw64/some/lib/libws2_32.dll in the MSYS Shell is breaking/converting the DLL to 32bit file (still according to Dependency Walker)... While copying/renaming it through Windows Explorer keep it unchanged... Still weird. If anyone has an explanation...
Or did I miss something about cp command usage...
Note: I already tried options like --preserve=all or --symbolic-link.
Thanks.
cp is somehow (either directly or due to the parent process that you're running it from) running as a 32-bit process. File System redirection is kicking in and you're actually copying ws2_32.dll from the C:\Windows\SysWOW64 directory instead - where it already exists as a 32-bit DLL.
32-bit applications can access the native system directory by substituting %windir%\Sysnative for %windir%\System32. WOW64 recognizes Sysnative as a special alias used to indicate that the file system should not redirect the access.

delphi 2009 compile packages

i truly don't get it.
trying to recompile the qr5 packages, and is impossible with this Delphi.
build the QR5Run_Rad6.bpl, everything is fine.
when i install QR5Design_RAD6.bpl an error message appears
"its not possible to run the program since qr5run_rad.bpl is missing in your computer. try again installing your program to solve this problem."
just did!
clean build compile doesn't work in any order. closed the ide and reopened , still doesn't work.
what else is left?
clean all related dcp and bpl
QR5Design_RAD6.bpl <> qr5run_rad.bpl
And more importantly, the qr5run_rad.bpl needs to be found on the systempath in order for the IDE to find it so it can be used by the design time package.
In other words: you need to build the qr5run_rad.bpl as well as the QR5Design_RAD6.bpl. And you need to make sure that the qr5run_rad.bpl ends up in a folder that is on your system path, not just any old folder where you have the sources and/or dcu's.
In addition to what Marjan wrote:
Windows uses these places when looking for a DLL (or BPL, which is a DLL):
The directory from which the application loaded.
The system directory. Use the GetSystemDirectory function to get the path of this directory.
The 16-bit system directory. There is no function that obtains the path of this directory, but it is searched.
The Windows directory. Use the GetWindowsDirectory function to get the path of this directory.
The current directory.
The directories that are listed in the PATH environment variable. Note that this does not include the per-application path specified by the App Paths registry key. The App Paths key is not used when computing the DLL search path.
Delphi puts BPL files in a directory like C:\Documents and Settings\All Users\Documents\RAD Studio\8.0\Bpl which it adds to your PATH when Delphi is installed. For Delphi 2009, that Path would probably be C:\Documents and Settings\All Users\Documents\RAD Studio\6.0\Bpl on a Windows XP machine.
--jeroen

Setting library directories in configure scripts

I want to compile vim on a 64 bit Linux server. On this machine, all basic directories are on a common network drive. 32 bit libraries are stored in .../lib, and 64 bit libraries in .../lib64.
When I run the configure script, it finds that X11 is in /usr/X11R6, and adds -L/usr/X11R6/lib to the linker flags. Of course it won't compile, because the 64 bit libraries are in /usr/X11R6/lib64.
I tried setting the environment variable LDIRS=-L/usr/X11R6/lib64 before running configure. It didn't help, because in the linking phase, it preceded -L/usr/X11R6/lib to my LDFLAGS variable, so it still wanted to find the library files in the wrong directory.
Is there any way to force the configure script to find library files on a particular location?

How to access the ProgramFiles environment variable from nmake on x64 machines?

I try to get the path to the ProgramFiles environmental variable, that is supposed to expand to C:\Program Files (x86) on a x64 machine and to C:\Program Files on a x86 machine.
The problems is that in the nmake file if I do:
all:
echo $(PROGRAMFILES)
This will expand to C:\Program Files everytime and this is wrong.
Environment details from a x64 machine:
ProgramFiles(x86)=C:\Program Files (x86)
ProgramW6432=C:\Program Files
:: this one is special, if will return different results based on current process x86/x64
ProgramFiles=C:\Program Files (x86) or C:\Program Files
PROCESSOR_ARCHITECTURE=x86 or x64
Now the updated question is how to get the location of x86 program files inside nmake, in a way this will work on both x86 and x64 machines?
This expression seems to work on 64-bit Windows 7, with nmake running in both 32-bit and 64-bit:
%%PROGRAMFILES(x86)%%
e.g.
LC = %%PROGRAMFILES(x86)%%\Microsoft SDKs\Windows\v7.0A\bin\lc.exe
If you're on an x64 machine it is totally legal that %ProgramFiles% points to C:\Program Files - from within a 64-bit program's environment.
The variable you have to use to get the x86 counterpart is %ProgramFiles(x86)%.
Which one to use can be determined by evaluating the current OS's architecture that is set in the PROCESSOR_ARCHITECTURE environment variable (which is e.g. set to AMD64). Or simply try to get %ProgramFiles(x86)% and if it is empty get the content of %ProgramFiles%.
Another approach would be to start a 32-bit cmd.exe and run your make there. It is located in C:\Windows\SysWOW64.

Resources