Home > Mobile >  How to get IP address in Pascal
How to get IP address in Pascal

Time:03-17

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.

CodePudding user response:

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;

CodePudding user response:

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.

  • Related