1

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')]
Sam M
  • 4,136
  • 4
  • 29
  • 42
Rafał Developer
  • 2,135
  • 9
  • 40
  • 72
  • 1
    I cannot reproduce. I also doubt the error message. No Delphi compiler I can recall ever said `[Pascal Error]`. Are you really using Delphi? And which version? – David Heffernan Apr 23 '13 at 08:23
  • I working with Borland Developer Studio 2006 – Rafał Developer Apr 23 '13 at 08:27
  • OK, I've tagged that in the question. Still cannot reproduce. Is there a unit named `ShellAPI` in your search path that is found before the RTL unit? – David Heffernan Apr 23 '13 at 08:28
  • it is the first time when I see [Pascal Error]...I believe it should be [Fatal Error], or I'm wrong? – RBA Apr 23 '13 at 08:29
  • 1
    Delphi is son of Pascal and probably in Borland Developer 2006 they write [Pascal] - but as I told you I am beginner. – Rafał Developer Apr 23 '13 at 08:32
  • Very strange, specially dotted filenamesin that (2006) period. Is this maybe some Delphi.NET version? – Marco van de Voort Apr 23 '13 at 08:35
  • 1
    @RBA I added picture to post – Rafał Developer Apr 23 '13 at 08:35
  • @David Heffernan as I told you I am beginner and before I think my error is small problem I copy this and I would like to check how is it working. – Rafał Developer Apr 23 '13 at 08:37
  • @Marco van de Voort Yes this is Delphi .Net version in Borland 2006 – Rafał Developer Apr 23 '13 at 08:39
  • what OS version are you using? – RBA Apr 23 '13 at 08:40
  • 1
    Are you 100% sure you want to be using the .net compiler? I would recommend using the native compiler instead. – David Heffernan Apr 23 '13 at 08:47
  • @David Heffernan in my job they have very old application which using this :( terrible... and I have to learn Delphi but at the beginning I make some examples from book but one of them isn`t work. – Rafał Developer Apr 23 '13 at 08:52
  • It's weird. Let's try some different variants to see if they compile: 1. `ShellExecute(0, 'open', nil, nil, nil, SW_SHOW);` 2. `ShellExecute(0, 'open', 'blah', 'blah', 'blah', SW_SHOW);` None of these is sensible to run, I'm just trying to work out why the compiler objects. – David Heffernan Apr 23 '13 at 08:58
  • @David Heffernan now software compile correct. Do you know where was problem? – Rafał Developer Apr 23 '13 at 09:17
  • Jedi CodeLibrary had a class for simplified launching programs using CreateProcess win api. in general JCL had support for Delphi.NET. Dunno if they still retain it and if that uint had it, but worth to check. – Arioch 'The Apr 23 '13 at 09:30
  • @Rafael - do Ctrl+Click over ShellExecute and see what is the actual declaration of it and quote it. Most probably native low-level trick - casting to PChar - was redundant for .Net wrappers. But do show the declaration if you want to let someone see what happened. PS: also, please, do fill proper tags when asking questions – Arioch 'The Apr 23 '13 at 09:32
  • 1
    @Arioch 'The I edited my post and I added information which I get when I click ctrl + click – Rafał Developer Apr 23 '13 at 09:43

1 Answers1

0

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.

David Heffernan
  • 601,492
  • 42
  • 1,072
  • 1,490
  • Now I get this errors -> [Pascal Error] Engine.pas(41): E2089 Invalid typecast [Pascal Fatal Error] Project1.dpr(18): F2063 Could not compile used unit 'Engine.pas' – Rafał Developer Apr 23 '13 at 09:45
  • When I use this ShellExecute(0, 'open', Path, nil, nil, SW_SHOW); I get this [Pascal Error] Engine.pas(41): E2250 There is no overloaded version of 'ShellExecute' that can be called with these arguments – Rafał Developer Apr 23 '13 at 09:48
  • 1
    this is working correct -> ShellExecute(0, 'open', Path, '', '', SW_SHOW); – Rafał Developer Apr 23 '13 at 09:49
  • Thanks for help and a lot of your time – Rafał Developer Apr 23 '13 at 09:49
  • And since the declaration error, @Rafael-JuniorMVCDeveloper would better to fix his `TEngine.Execute` by saving `shellexecute` reusl into a variable and checking that it is `>=32` and raising exception otherwise. – Arioch 'The Apr 23 '13 at 10:30
  • 1
    @Arioch'The I think the best solution is to use `ShellExecuteEx` which does use the standard last error mechanism: http://blogs.msdn.com/b/oldnewthing/archive/2012/10/18/10360604.aspx – David Heffernan Apr 23 '13 at 10:35
  • Maybe interop passes NIL for an empty string literal ? – Marco van de Voort Apr 23 '13 at 12:45
  • @MarcovandeVoort If it did it would then be impossible to pass `'\0'`, the empty C string. In C# a string is a reference type and `null` can be passed. It looks like a weakness. That said, it's not exactly mainstream is it, the Delphi.net compiler?! – David Heffernan Apr 23 '13 at 12:53
  • I own a couple of them, but like Prism didn't even bother to start/test them. (and I have some VS experience, though more ASP.NET than standalone C# apps) It's kind of illogical to on one side choose the platform "everybody" is doing, but at the same time to choose an obscure vendor's tools for it. Either you conform or not. – Marco van de Voort Apr 23 '13 at 14:37