I have some code that compiles fine with D7 but fails with D2010.
Obviously it is an Unicode issue:
The compile error is:
E2251 Ambiguous overloaded call to ‘StrPas’
Here is the whole procedure:
procedure GetVersionInfo;
type
PLangCharSetInfo = ^TLangCharSetInfo;
TLangCharSetInfo = record
Lang: Word;
CharSet: Word;
end;
var
FileName: array [0..260] of Char;
SubBlock: array [0..255] of Char;
VerHandle: Cardinal;
Size: Word;
Buffer: Pointer;
Data: Pointer;
DataLen: LongWord;
LangCharSetInfo: PLangCharSetInfo;
LangCharSetString: string;
begin
LabelComments.Caption := 'No version information for this program is available!';
{Get size and allocate buffer for VerInfo}
if GetModuleFileName(hInstance, FileName, SizeOf(FileName)) > 0 then
begin
Size := GetFileVersionInfoSize(FileName, VerHandle);
if Size > 0 then
begin
GetMem(Buffer, Size);
try
if GetFileVersionInfo(FileName, VerHandle, Size, Buffer) then
begin
{Query first language and that language blocks version info}
if VerQueryValue(Buffer, '\VarFileInfo\Translation', Pointer(LangCharSetInfo), DataLen) then
begin
LangCharSetString := IntToHex(LangCharSetInfo^.Lang, 4) +
IntToHex(LangCharSetInfo^.CharSet, 4);
if VerQueryValue(Buffer, StrPCopy(SubBlock, '\StringFileInfo\' + LangCharSetString + '\ProductName'), Data, DataLen) then
begin
LabelProductName.Caption := StrPas(Data);
Caption := LabelProductName.Caption;
end;
if VerQueryValue(Buffer, StrPCopy(SubBlock, '\StringFileInfo\' + LangCharSetString + '\FileVersion'), Data, DataLen) then
LabelVersion.Caption := StrPas(Data);
if VerQueryValue(Buffer, StrPCopy(SubBlock, '\StringFileInfo\' + LangCharSetString + '\LegalCopyright'), Data, DataLen) then
LabelCopyright.Caption := StrPas(Data);
if VerQueryValue(Buffer, StrPCopy(SubBlock, '\StringFileInfo\' + LangCharSetString + '\Comments'), Data, DataLen) then
LabelComments.Caption := StrPas(Data);
end;
end;
finally
FreeMem(Buffer, Size);
end;
end
end;
end;
The doc for StrPas says
function StrPas(const Str: PAnsiChar): AnsiString; overload;
This function is provided fasor backwards compatibility only.
To convert a null-terminated string to an AnsiString or native
Delphi language string, use a typecast or an signment.
So the question is should I remove all calls to StrPas ?
The only way I make this to compile is to do a hardcast to PAnsi char like:
LabelProductName.Caption := StrPas(PAnsiChar(Data));
You edited your question with a full compiling sample. Good!
It is probably the easiest if you’d use the JCL for this (link is below).
Then you could use TJclFileVersionInfo, which does all you want, and takes into account some esotheric things that the VersionInfo can hold.
Then your business logic would become something like this:
And in the UI, you will need to call your business logic, and put the results into the various controls.
–jeroen
Answer before edit:
Your code does not compile as is, so without more context, it is hard to answer your quest.
What are the data types of Buffer, SubBlock, LongCharSetString and DataLen? How did you obtain Buffer?
Is Data really meant to be a Pointer to (Ansi or Unicode) characters? Shouldn’t it ultimately be of pointing to PVSFixedFileInfo?
(A side question: why is your business logic inside the UI? If you had split your logic into a separate function somewhere, you’d probably have a compiling routine that could have served as the base for your question. That might have answered the question in the first place).
For questions like yours, I usually take a peek at units in the the JCL or JVCL. They have put a lot of effort in those to be Unicode compatible.
Their code that use VerQueryValue is this one in unit JclFileUtils, method VersionFixedFileInfo:
Hope this gets you started in finding your solution.
–jeroen