4

In Delphi 10.4, When trying to use Winapi.ShLwApi.StrFormatByteSize64 to convert an Int64 file-size value into a formatted string I get a runtime error:

var
  ThisSize: Int64;
  pszBuf: PWideChar;
  cchBuf: Cardinal;

Winapi.ShLwApi.StrFormatByteSize64(ThisSize, pszBuf, cchBuf);

Error message:

--------------------------- MyApp.exe - Entry point not found
--------------------------- The Procedure Entry point "StrFormatByteSize64W" was not found in the DLL "C:\DELPHI\MyApp\Win32\Debug\MyApp.exe".
--------------------------- OK


How to solve this problem?

4

1 回答 1

7

The remarks for the function in the documentation say:

StrFormatByteSize64 can be used for either ANSI or Unicode characters. However, while StrFormatByteSize64A can be called directly, StrFormatByteSize64W is not defined. When StrFormatByteSize64 is called with a Unicode value, StrFormatByteSizeW is used.

The Delphi import is declared as:

function StrFormatByteSize64; external shlwapi32 name 'StrFormatByteSize64W';

In other words, this is a translation error in the Delphi RTL. The function StrFormatByteSize64W does not exist in shlwapi.dll.

As the documentation says, call StrFormatByteSize instead. This is handled for you by the Windows header files, but Embarcadero have not picked up this nuance when translating them.

This program demonstrates:

{$APPTYPE CONSOLE}

uses
  System.SysUtils,
  Winapi.ShLwApi;

procedure Main;
var
  ThisSize: Int64;
  szBuf: array[0..255] of Char;
  cchBuf: Cardinal;
begin
  ThisSize := Int64(1024)*1024*1024*256;
  cchBuf := Length(szBuf);
  Winapi.ShLwApi.StrFormatByteSize(ThisSize, szBuf, cchBuf);
  Writeln(szBuf);
end;

begin
  try
    Main;
  except
    on E: Exception do
      Writeln(E.ClassName, ': ', E.Message);
  end;
  Readln;
end.

Output:

256 GB

I have reported this to Embarcadero: https://quality.embarcadero.com/browse/RSP-29943

于 2020-07-04T15:46:07.170 回答