Keros
Keros

Reputation: 11

How to get IP address in Pascal

i am getting these two Errors trying to view IP address and show in a messagebox

Error looks like this

[dcc32 Error] Unit1.pas(38): E2010 Incompatible types: 'PAnsiChar' and 'PWideChar' => Error1

and

[dcc32 Error] Unit1.pas(40): E2010 Incompatible types: 'string' and 'array[1..1024] of Byte' => Error2

I could do this in C/C++ but i wanted to try something new in Delphi

My source code Looks like this

unit Unit1;

interface

uses
  Winapi.Windows, Winapi.Wininet, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls;

type
  TForm1 = class(TForm)
    Button1: TButton;
    Label1: TLabel;
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
  var
    hInet: HINTERNET;
    hFile: HINTERNET;
    buffer: array[1..1024] of byte;
    bytesRead: DWORD;
    url : String;

begin
  url := 'https://icanhazip.com';
  hInet := InternetOpen(PChar(application.title),INTERNET_OPEN_TYPE_PRECONFIG,nil,nil,0);
  hFile := InternetOpenUrlA(hInet, PChar(url), nil, 0, 0, 0); //Error 1
  InternetReadFile(hFile,@buffer,SizeOf(buffer),bytesRead); // Error 2
  showmessage(buffer);

end;

end.

Please what am I doing wrongly?

Edit

Okay, InternetOpenUrl Worked,however , it still gives me error on the showmessage(buffer)

Code looks like this now

unit Unit1;

interface

uses
  Winapi.Windows, Winapi.Wininet, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls;

type
  TForm1 = class(TForm)
    Button1: TButton;
    Label1: TLabel;
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
  var
    hInet: HINTERNET;
    hFile: HINTERNET;
    buffer: array[1..1024] of byte;
    bytesRead: DWORD;
    url : String;

begin
  url := 'https://icanhazip.com';
  hInet := InternetOpen(PChar(application.title),INTERNET_OPEN_TYPE_PRECONFIG,nil,nil,0);
  hFile := InternetOpenUrl(hInet, PChar(url), nil, 0, 0, 0);
  InternetReadFile(hFile,@buffer,SizeOf(buffer),bytesRead);
  showmessage(buffer);

end;

end.

Edit2

My code Looks like this now

unit Unit1;

interface

uses
  Winapi.Windows, Winapi.Wininet, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls;

type
  TForm1 = class(TForm)
    Button1: TButton;
    Label1: TLabel;
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
  var
    hInet: HINTERNET;
    hFile: HINTERNET;
    buffer: String;
    bytesRead: DWORD;
    url : String;
    szMessage : String;
    i : integer;


begin
  //url := 'https://icanhazip.com';
  hInet := InternetOpen(PChar(application.title),INTERNET_OPEN_TYPE_PRECONFIG,nil,nil,0);
  hFile := InternetOpenUrl(hInet, PChar('https://icanhazip.com'), nil, 0, 0, 0);
  InternetReadFile(hFile,@buffer,SizeOf(buffer),bytesRead);

  //showmessage(buffer);
  Label1.Caption := buffer;

end;

end.

Upvotes: 1

Views: 855

Answers (2)

Uwe Raabe
Uwe Raabe

Reputation: 47704

The first error happens because you call the AnsiChar version of the function.

Use InternetOpenUrl instead of InternetOpenUrlA.

The second happens in the line below you expect it. ShowMessage expects a string and not an array of byte.

Edit: To get a string out of your array of bytes to be passed to ShowMessage, you need to know in what encoding the bytes are sent. Assuming that is UTF-8, the conversion can simply be done with:

ShowMessage(TEncoding.UTF8.GetString(Slice(buffer, bytesRead)))

Edit 2: OK, for XE8 you have to do a bit more work.

procedure TForm1.Button1Click(Sender: TObject);
  var
    hInet: HINTERNET;
    hFile: HINTERNET;
    buffer: TBytes;
    bytesRead: DWORD;
    url : String;

begin
  url := 'https://icanhazip.com';
  hInet := InternetOpen(PChar(application.title),INTERNET_OPEN_TYPE_PRECONFIG,nil,nil,0);
  hFile := InternetOpenUrl(hInet, PChar(url), nil, 0, 0, 0);
  SetLength(buffer, 1024);
  InternetReadFile(hFile,@buffer[0],Length(buffer),bytesRead);
  showmessage(TEncoding.UTF8.GetString(buffer, 0, bytesRead));    
end;

Upvotes: 1

Rob Lambden
Rob Lambden

Reputation: 2293

In C/C++ you typically use a NUL terminated string -and allocate the storage to hold that string yourself. This is what you have done in your code with the BYTE array.

In Delphi a string is a native type, not just a pointer to NUL terminated character data.

From the Error message you provided the error happens on the call to ShowMessage, not on the call to InternetReadFile.

You need to pass a string variable to ShowMessage.

You could try this:

var
  szMessage: String;
  i: Integer;

  SetLength(szMessage, bytesread);
  for i =1 to bytesread do
    szMessage[i]:=buffer[i-1];
  ShowMessage(szMessage);

There are ways you can do this more compactly, but as someone who has moved from C++ to mainly using Delphi these days I think looking at the operation this way helps to understand the differences between the two languages.

Upvotes: 0

Related Questions