如何在 Pascal 中获取 IP 地址

发布于 2025-01-14 13:06:15 字数 3432 浏览 1 评论 0原文

我在尝试查看 IP 地址并在消息框中显示时遇到这两个错误 错误

如下所示

[dcc32 错误] Unit1.pas(38): E2010 不兼容的类型:“PAnsiChar”和 'PWideChar' =>错误1

​​和

[dcc32 错误] Unit1.pas(40): E2010 不兼容的类型:“string”和 '字节数组[1..1024]' =>错误2

我可以在 C/C++ 中做到这一点,但我想在 Delphi 中尝试一些新的东西

我的源代码看起来像这样

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.

请问我做错了什么?

编辑

好的,InternetOpenUrl工作了,但是,它仍然在showmessage(缓冲区)上给我错误

代码现在看起来像这样

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

我的代码看起来像现在这个

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.

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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

无语# 2025-01-21 13:06:15

第一个错误发生是因为您调用了该函数的 AnsiChar 版本。

使用 InternetOpenUrl 而不是 InternetOpenUrlA

第二个发生在您期望的下面一行。 ShowMessage 需要一个字符串,而不是字节数组

编辑:
要从字节数组中获取字符串并传递给 ShowMessage,您需要知道字节以什么编码发送。假设是 UTF-8,转换可以简单地完成:

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

编辑 2:
好吧,对于 XE8 你还需要做更多的工作。

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;

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;
爱的十字路口 2025-01-21 13:06:15

在 C/C++ 中,您通常使用 NUL 结尾的字符串 - 并自己分配存储空间来保存该字符串。这就是您在代码中使用 BYTE 数组所做的事情。

在 Delphi 中,string 是一种本机类型,而不仅仅是指向 NUL 终止字符数据的指针。

从您提供的错误消息来看,错误发生在对 ShowMessage 的调用上,而不是在对 InternetReadFile 的调用上。

您需要将字符串变量传递给 ShowMessage。

您可以尝试这样做:

var
  szMessage: String;
  i: Integer;

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

有一些方法可以更紧凑地做到这一点,但作为最近从 C++ 转向主要使用 Delphi 的人,我认为以这种方式查看操作有助于理解两种语言之间的差异。

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文