在Delphi中从Windows消息中获取串口的友好名称

在Delphi中从Windows消息中获取串口的友好名称,delphi,winapi,serial-port,Delphi,Winapi,Serial Port,我在使用delphi从DEV_BROADCAST_端口获取友好名称(dbcp_name)时遇到问题 我曾尝试使用microsoft帮助文档,该文档说它是指向以null结尾的字符串的指针,但在该页面上有一条注释表明它是一个可变长度的结构,dbcp_name是一个包含端口名实际字符的数组 我试图提取这个,但我目前还没有找到一种方法,因为当我得到它返回任何东西时,它完全是胡言乱语 我使用的代码如下: PDevBroadcastPort = ^DEV_BROADCAST_PORT; DEV_BROAD

我在使用delphi从DEV_BROADCAST_端口获取友好名称(dbcp_name)时遇到问题

我曾尝试使用microsoft帮助文档,该文档说它是指向以null结尾的字符串的指针,但在该页面上有一条注释表明它是一个可变长度的结构,dbcp_name是一个包含端口名实际字符的数组

我试图提取这个,但我目前还没有找到一种方法,因为当我得到它返回任何东西时,它完全是胡言乱语

我使用的代码如下:

PDevBroadcastPort = ^DEV_BROADCAST_PORT;

DEV_BROADCAST_PORT = packed record
    dbcp_size : DWORD ;
    dbcp_devicetype : DWORD;
    dbcp_reserved : DWORD ;
    dbcp_name : array[0..0] of ansichar; //TCHAR dbcp_name[1]; not valid
end;
我尝试了数组长度的不同值,我在某处读到这是正确的声明,但我不完全确定。另外,注释掉的行是microsoft文档在C中给出的行++

为了提取信息,我尝试了以下方法:

var
  PData: PDevBroadcastPort;

  FName: string;

  ...

  PData := PDevBroadcastPort(Msg.lParam);

  ShowMessage('Length '+Inttostr(length(PData^.dbcp_name)));

  FName := '';

  i:=0;

  while((PData^.dbcp_name[i]) <> #0) and (i < 100) do
      begin
          FName := FName + (PData.dbcp_name[i]);

          i := i +1;

          ShowMessage(FName); 
      end;
var
PData:PDEV广播端口;
FName:字符串;
...
PData:=PDevBroadcastPort(Msg.lParam);
ShowMessage('Length'+Inttostr(Length(PData^.dbcp_name)));
FName:='';
i:=0;
而((PData^.dbcp_name[i])#0)和(i<100)则
开始
FName:=FName+(PData.dbcp_name[i]);
i:=i+1;
ShowMessage(FName);
终止
我曾尝试将while循环设置为在数据结构的长度处终止,但如果我不设置它,那么它将变得非常庞大

如果我遗漏了这个问题所需的任何代码,请让我知道,我会尽快获得它


感谢

文档没有说它是指向以null结尾的字符串的指针;它表示它是以null结尾的字符串。这对于在长度仅为一个元素的记录末尾声明的数组是典型的

在指定的记录大小之后,实际上有更多的内存,该内存保存字符串的剩余字符。指向该记录字段的指针也是指向字符数据的指针

FName := PAnsiChar(@PData.dbcp_name);
假设已禁用对该段代码的边界检查,那么数组遍历代码也应该可以工作(否则,当程序检测到您读取的内容超出了数组的第一个元素时,会出现异常)

这一切都假定
PData
实际上是指向
Dev\u Broadcast\u Port
结构的指针。你没有透露你传递的信息,所以我不知道你是否真的拥有你认为你拥有的

FName := PChar(@PData.dbcp_name);
如果您使用的是Delphi 2009或更高版本,那么C声明中的
TCHAR
类型相当于Delphi的
WideChar
类型。将字段解释为AnsiChar的数组将得到错误的结果,尽管对于大多数端口名,数组可能看起来像是以null结尾的一个字符串的列表。除非您确定您拥有非Unicode数据,否则您应该只使用
Char
PChar
,并让Delphi版本确定您拥有的数据类型

FName := PChar(@PData.dbcp_name);

文档没有说它是指向以null结尾的字符串的指针;它表示它是以null结尾的字符串。这对于在长度仅为一个元素的记录末尾声明的数组是典型的

在指定的记录大小之后,实际上有更多的内存,该内存保存字符串的剩余字符。指向该记录字段的指针也是指向字符数据的指针

FName := PAnsiChar(@PData.dbcp_name);
假设已禁用对该段代码的边界检查,那么数组遍历代码也应该可以工作(否则,当程序检测到您读取的内容超出了数组的第一个元素时,会出现异常)

这一切都假定
PData
实际上是指向
Dev\u Broadcast\u Port
结构的指针。你没有透露你传递的信息,所以我不知道你是否真的拥有你认为你拥有的

FName := PChar(@PData.dbcp_name);
如果您使用的是Delphi 2009或更高版本,那么C声明中的
TCHAR
类型相当于Delphi的
WideChar
类型。将字段解释为AnsiChar的数组将得到错误的结果,尽管对于大多数端口名,数组可能看起来像是以null结尾的一个字符串的列表。除非您确定您拥有非Unicode数据,否则您应该只使用
Char
PChar
,并让Delphi版本确定您拥有的数据类型

FName := PChar(@PData.dbcp_name);

dbcp\u name
字段包含实际字符。字符数据的长度减去空终止符后为
dbcp\u size-SizeOf(DEV\u BROADCAST\u PORT)
,因此您可以这样获取名称:

type
  DEV_BROADCAST_PORTA = packed record
    dbcp_size : DWORD;
    dbcp_devicetype : DWORD;
    dbcp_reserved : DWORD;
    dbcp_name : array[0..0] of AnsiChar;
  end; 

  DEV_BROADCAST_PORTW = packed record
    dbcp_size : DWORD;
    dbcp_devicetype : DWORD;
    dbcp_reserved : DWORD;
    dbcp_name : array[0..0] of WideChar;
  end; 

  {$IFDEF UNICODE}
  DEV_BROADCAST_PORT = DEV_BROADCAST_PORTW;
  {$ELSE}
  DEV_BROADCAST_PORT = DEV_BROADCAST_PORTA;
  {$ENDIF}
  PDEV_BROADCAST_PORT = ^DEV_BROADCAST_PORT;


dbcp\u name
字段包含实际字符。字符数据的长度减去空终止符后为
dbcp\u size-SizeOf(DEV\u BROADCAST\u PORT)
,因此您可以这样获取名称:

type
  DEV_BROADCAST_PORTA = packed record
    dbcp_size : DWORD;
    dbcp_devicetype : DWORD;
    dbcp_reserved : DWORD;
    dbcp_name : array[0..0] of AnsiChar;
  end; 

  DEV_BROADCAST_PORTW = packed record
    dbcp_size : DWORD;
    dbcp_devicetype : DWORD;
    dbcp_reserved : DWORD;
    dbcp_name : array[0..0] of WideChar;
  end; 

  {$IFDEF UNICODE}
  DEV_BROADCAST_PORT = DEV_BROADCAST_PORTW;
  {$ELSE}
  DEV_BROADCAST_PORT = DEV_BROADCAST_PORTA;
  {$ENDIF}
  PDEV_BROADCAST_PORT = ^DEV_BROADCAST_PORT;


我认为你需要从内存转储开始,看看有什么。调试器中的CPU视图可以显示你想要的内存。为它提供存储在
PData
中的地址,并查看它是否符合文档中所述的预期。我认为您需要从内存转储开始,以查看其中的内容。调试器中的CPU视图可以显示您想要的任何内存。将存储在
PData
中的地址赋给它,看看它是否符合文档中所说的预期。我不必做任何边界检查,但我更改了:FName:=FName+(PData.dbcp_name[I]);to FName:=FName+PAnsiChar(@PData.dbcp_name[i]);谢谢?如果仍然有循环,那么将附加多个字符串,而不仅仅是单个字符。如果没有循环,则根本不需要
i
变量。我开始怀疑你是在使用Delphi 209还是更高版本,你的字符实际上是WideChar而不是AnsiChar。您描述的代码不应该工作。我还将记录更改为