views:

3457

answers:

3

Hi I have been using this function in Delphi 2006, but now with D2010 it throws an error. I think it is related to the switch to Unicode.

  Function TWinUtils.GetTempFile(Const Extension: STRING): STRING;
  Var
     Buffer: ARRAY [0 .. MAX_PATH] OF char;
  Begin
    Repeat
      GetTempPath(SizeOf(Buffer) - 1, Buffer);
      GetTempFileName(Buffer, '~~', 0, Buffer);
      Result := ChangeFileExt(Buffer, Extension);
    Until not FileExists(Result);
  End;

What should I do to make it work?

EDIT

I get an 'access violation' when the ChangeFileExt is called

A: 

With Delphi 2009, Char is a unicode char. The function probably requires an array of AnsiChar.

Just checked it. Both GetTempFilename and GetTempPath require a PWideString.

What is the error message?

Gamecat
Are you should you don't mean `PWideChar`? `PWideString` is something else entirely.
Rob Kennedy
+6  A: 

Windows.Pas

function GetTempFileName(lpPathName, lpPrefixString: PWideChar;
  uUnique: UINT; lpTempFileName: PWideChar): UINT; stdcall;

function GetTempPath(nBufferLength: DWORD; lpBuffer: PWideChar): DWORD; stdcall;

SysUtils.Pas

function ChangeFileExt(const FileName, Extension: string): string;

Try this

  Function TWinUtils.GetTempFile(Const Extension: STRING): STRING;
  Var
     Buffer: ARRAY [0 .. MAX_PATH] OF WideChar;
  Begin
    Repeat
      GetTempPath(Length(Buffer), Buffer);
      GetTempFileName(Buffer, '~~', 0, Buffer);
      Result := ChangeFileExt(Buffer, Extension);
    Until not FileExists(Result);
  End;

or this

  Function GetTempFile(Const Extension: String): String;
  Var
     Buffer: String;
  Begin
      SetLength(Buffer,MAX_PATH);
    Repeat
      GetTempPath( MAX_PATH, PChar( Buffer) );
      GetTempFileName(PChar( Buffer), '~~', 0, PChar( Buffer));
      Result := ChangeFileExt(Buffer, Extension);
    Until not FileExists(Result);
  End;

For Delphi, Char and PChar types are WideChar and PWideChar types, respectively.

If you use any Windows API’s that return data into char buffers , those buffers need to be redeclared as arrays of bytes or an array of AnsiChar.

If you are calling these Windows API’s and sending in buffers, if have been using the sizeof function when telling the API how long your buffer is. Those calls need to be changed to the Length function, as the Windows widechar API’s require the number of characters, not the number of bytes.

Bye.

RRUZ
And the reason the old code was a problem is the SizeOf(Buffer) - 1 in GetTempPath(). SizeOf an array of Chars was the same as the Length for Delphi before 2009, because SizeOf(AnsiChar) = 1. With Delphi 2009 and later, SizeOf(Char) = SizeOf(WideChar) = 2, so the code was asking GetTempPath() to fill the buffer with more characters than it could hold.
jasonpenny
the second option works thanks :)
Charles Faiga
I tried both options in "delphi 2010", and they worked ok. ;)
RRUZ
Char is not Widechar! It is UnicodeChar. There is a slight difference.
Gamecat
Gamecat in the delphi 2010 help ms-help://embarcadero.rs2010/rad/Simple_Types.html "The general character type is Char, which is equivalent to WideChar now that the default string type is UnicodeString".
RRUZ
A: 

Use GetTempPathA and GetTempFileNameA, the Ansi versions of GetTempPath and GetTempFileName. They are still available in Delphi 2009, and mentioned in the Delphi 2009 help file, but not advertised.

DaveBoltman
On Windows NT OS versions most if not all *A versions of the API functions are just stubs that convert parameters and call the *W versions of same function. So in Delphi 2009+ you would convert internal wide char data to Ansi, call *A function, which converts internally to wide chars and back, and the program would take the result and convert it back to wide chars. Would you say that going this route makes any sense?
mghie