RTTI访问VCL的私有方法,例如TCustomForm.SetWindowState

时间:2016-06-19 08:24:16

标签: delphi rtti

在关于关闭类帮助程序漏洞的辩论中,它允许轻松访问Delphi 10.1柏林中某个类的私有成员(字段和方法),但通常声称

  • 扩展RTTI允许访问使用(扩展)RTTI启用编译的类的私有成员,并且
  • 所有VCL / RTL / FMX类都已启用此功能。

但是,如果我运行这个简单的单元(一个带有一个TListBox的简单表单,没有别的):

unit RttiAccessTest;

interface

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

type
  TForm16 = class(TForm)
    ListBox1: TListBox;
    procedure FormCreate(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form16: TForm16;

implementation

{$R *.dfm}

function GetMethodString(const MethodName: string): string;
var
  M: TRTTIMethod;
  I: Integer;
begin
  M := TRttiContext.Create.GetType(TCustomForm).GetMethod(MethodName);
  if Assigned(M) then
    Result := 'Method ' + MethodName + ': ''' + M.ToString + ';'''
  else
    Result := 'Method ' + MethodName + ' cannot be found';
end;

procedure TForm16.FormCreate(Sender: TObject);
begin
  Listbox1.Items.Add(GetMethodString('SetWindowState'));
  Listbox1.Items.Add(GetMethodString('ShowModal'));
end;

end.

列表框中的文字是:

Method SetWindowState cannot be found 
Method ShowModal: 'function ShowModal: Integer;'

这意味着我无法访问SetWindowState的此私有方法TCustomForm。这是因为并非RTL / VCL / FMX中的所有类都扩展了RTTI,或者我做错了什么?

如果我做错了什么或遗忘了什么,那又怎样?换句话说,我需要做些什么才能让RTTI访问SetWindowState TCustomForm?我无法在西雅图或更早的时候获得此访问权限。

注意

我知道如何访问该方法,使用类助手仍然可以获取私有方法的地址这一事实,但这不是我的问题。 我特别询问如何使用RTTI执行此操作

2 个答案:

答案 0 :(得分:3)

显而易见的结论是,虽然此类型是使用扩展RTTI编译的,但私有方法不包含RTTI。

答案 1 :(得分:1)

要使用RTTI访问严格私有/私有方法,请使用编译器指令{$RTTI}

  

语法

     

$ RTTI指令的一般语法可以分为三个部分。 $ RTTI的基本形式如下:

     

{$ RTTI INHERIT | EXPLICIT [visibility-clause]}

     

<强>可视性子句:

     

方法|属性|字段(可见性 - 表达式)

     

<强>可视性表达

     

[vcPrivate],[vcProtected],[vcPublic],[vcPublished];

示例:

{$RTTI EXPLICIT METHODS([vcPublic, vcProtected, vcPrivate])}

设置public,protected和private方法的可见性

注意:此指令的范围是本地,而RTL/VCL/FMX关闭了这些选项,这意味着可以访问 protected / private < / strong>无法使用RTTI方法。