Question

I am beginner of Delphi now I would like to learn this language but I have got error and I don`t know where is problem and how to fix it. This example I take it from book to delphi.

Error

[Pascal Error] Engine.pas(41): E2250 There is no overloaded version of 'ShellExecute' that can be called with these arguments

All code:

unit Engine;
interface
uses Windows, Classes, SysUtils;
type
  TTemplate = array of String;
  TEngine = class
private
  FFileName : String;
  FFileLines : TStringList;
protected
  procedure Execute(Path : String); virtual;
public
  Pattern : TTemplate;
  Replace : TTemplate;
  procedure Parse;
  constructor Create(FileName : String);
  destructor Destroy; override;
end;
implementation
{ TEngine }
uses ShellAPI; // włączenie modułu ShellAPI
constructor TEngine.Create(FileName : String);
begin
  FFileName := FileName; // przypisanie wartości parametru do
  FFileLines := TStringList.Create; // utworzenie typu TStringList
  FFileLines.LoadFromFile(FileName); // załadowanie zawartości
  inherited Create;
end;
destructor TEngine.Destroy;
begin
  FFileLines.Free; // zwolnienie typu
  { zwolnienie tablic }
  Pattern := nil;
  Replace := nil;
  DeleteFile('temporary.html'); // wykasowanie pliku tymczasowego
  inherited; // wywołanie destruktora klasy bazowej
end;
procedure TEngine.Execute(Path: String);
begin
  // otwarcie pliku w przeglądarce Internetowej
  ShellExecute(0, 'open', PChar(Path), nil, nil, SW_SHOW);
end;
procedure TEngine.Parse;
var
  i : Integer;
begin
  for I := Low(Pattern) to High(Pattern) do
  { zastąpienie określonych wartości w FFileLines }
  FFileLines.Text := StringReplace(FFileLines.Text, Pattern[i],
  Replace[i], [rfReplaceAll]);
  FFileLines.SaveToFile('temporary.html');
  Execute('temporary.html');
end;
end.

Place with error

ShellExecute(0, 'open', PChar(Path), nil, nil, SW_SHOW);

picture error enter image description here

Ctrl + click

[SuppressUnmanagedCodeSecurity, DllImport(shell32, CharSet = CharSet.Auto, SetLastError = True, EntryPoint = 'ShellExecute')]
function ShellExecute(hWnd: HWND; Operation, FileName, Parameters,
  Directory: string; ShowCmd: Integer): HINST; external;
[SuppressUnmanagedCodeSecurity, DllImport(shell32, CharSet = CharSet.Auto, SetLastError = True, EntryPoint = 'ShellExecute')]
Was it helpful?

Solution

Looking at the declaration of ShellExecute in the .net implementation of ShellAPI, it is clear what to do. Stop casting to PChar and write your code like this:

ShellExecute(0, 'open', Path, '', '', SW_SHOW);

I had not appreciated this until now, but it seems that the Windows API calls you make from Delphi.net use the same DllImport attribute as other .net languages. I guess that makes sense and these are just normal p/invoke calls as would be found in C# interop code.

Interestingly, you report that attempts to pass nil to one of these string parameters leads to a compiler error. That means that there's no easy way to pass the null pointer to an API function that expects a C string. What you would have to do is to use an overloaded external declaration that received a Pointer for the parameter which you want to pass nil to.

As an aside, the Embarcadero developers made a mistake in their DllImport declaration. They set SetLastError = True which is incorrect for ShellExecute which does not set the thread last error value.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top