Loading a Delphi executable and then accessing RTTI information

Hello,

Is it possible for a Delphi (Berlin 10.1) application to load another Delphi (Berlin 10.1) and access the RTTI information within it?

If that is not possible, could it possible be done (yeah, asking a lot here) with some hackery?

Thanks in advance,

Nick

My guess is that it is possible with a lot of work. Programs like TestComplete are able to access published properties of form components of Delphi programs under test. How you do it might take a bit of hackery as you say. In the case of Test Complete it requires some debug output from the compiler to help it.

Preparing Delphi Applications for Testing | TestComplete Documentation

My guess is this activity would be non-trivial.

I wrote a program that could extract the forms out of an exe file and generate a stub class for each form. It used RTTI, but the RTTI was actually from the program I was running, not the program I was extracting the forms from. One of the troubles with this method was RTTI only exists for code/components that are in the running program. To get around this, I created something like this

  lObjectTypes : TList<TClass>;
  lObjectTypes.Add(TForm);
  lObjectTypes.Add(TFrame);
  lObjectTypes.Add(TLabel);

  // Standard Controls
  lObjectTypes.Add(TMainMenu);
  lObjectTypes.Add(TPopupMenu);
  lObjectTypes.Add(TLabel);
  lObjectTypes.Add(TEdit);
  lObjectTypes.Add(TMemo);
  lObjectTypes.Add(TButton);
  lObjectTypes.Add(TCheckBox);
  lObjectTypes.Add(TRadioButton);
  lObjectTypes.Add(TListBox);
  lObjectTypes.Add(TComboBox);
  lObjectTypes.Add(TScrollBar);
  lObjectTypes.Add(TGroupBox);
  lObjectTypes.Add(TRadioGroup);
  lObjectTypes.Add(TPanel);
  lObjectTypes.Add(TActionList);

  // Additional
  lObjectTypes.Add(TBitBtn);
  lObjectTypes.Add(TSpeedButton);
  lObjectTypes.Add(TMaskEdit);
  lObjectTypes.Add(TStringGrid);
  lObjectTypes.Add(TDrawGrid);
  lObjectTypes.Add(TImage);
  lObjectTypes.Add(TShape);
  lObjectTypes.Add(TBevel);
  lObjectTypes.Add(TScrollBox);
  lObjectTypes.Add(TCheckListBox);
  lObjectTypes.Add(TSplitter);
  lObjectTypes.Add(TStaticText);
  lObjectTypes.Add(TControlBar);
  lObjectTypes.Add(TApplicationEvents);
  lObjectTypes.Add(TValueListEditor);
  lObjectTypes.Add(TLabeledEdit);
  lObjectTypes.Add(TColorBox);
  lObjectTypes.Add(TColorListBox);
  lObjectTypes.Add(TCategoryButtons);
  lObjectTypes.Add(TButtonGroup);
  lObjectTypes.Add(TDockTabSet);
  lObjectTypes.Add(TTabSet);
  lObjectTypes.Add(TChart);
  lObjectTypes.Add(TActionManager);
  lObjectTypes.Add(TActionMainMenuBar);
  lObjectTypes.Add(TPopupActionBar);
  lObjectTypes.Add(TActionToolbar);
  lObjectTypes.Add(TXPColorMap);
  lObjectTypes.Add(TStandardColorMap);
  lObjectTypes.Add(TTwilightColorMap);
  lObjectTypes.Add(TCustomizeDlg);

  // Win32
  lObjectTypes.Add(TTabControl);
  lObjectTypes.Add(TPageControl);
  lObjectTypes.Add(TImageList);
  lObjectTypes.Add(TRichEdit);
  lObjectTypes.Add(TTrackBar);
  lObjectTypes.Add(TProgressBar);
  lObjectTypes.Add(TUpDown);
  lObjectTypes.Add(THotKey);
  lObjectTypes.Add(TAnimate);
  lObjectTypes.Add(TDateTimePicker);
  lObjectTypes.Add(TMonthCalendar);
  lObjectTypes.Add(TTreeView);
  lObjectTypes.Add(TListView);
  lObjectTypes.Add(THeaderControl);
  lObjectTypes.Add(TStatusBar);
  lObjectTypes.Add(TToolBar);
  lObjectTypes.Add(TCoolBar);
  lObjectTypes.Add(TPageScroller);
  lObjectTypes.Add(TComboBoxEx);
  lObjectTypes.Add(TXPManifest);

  // System
  lObjectTypes.Add(TTimer);
  lObjectTypes.Add(TPaintBox);
  lObjectTypes.Add(TMediaPlayer);
  lObjectTypes.Add(TOleContainer);
  lObjectTypes.Add(TDdeClientConv);
  lObjectTypes.Add(TDdeClientItem);
  lObjectTypes.Add(TDdeServerConv);
  lObjectTypes.Add(TDdeServerItem);

  // Dialogs
  lObjectTypes.Add(TOpenDialog);
  lObjectTypes.Add(TSaveDialog);
  lObjectTypes.Add(TOpenPictureDialog);
  lObjectTypes.Add(TSavePictureDialog);
  lObjectTypes.Add(TOpenTextFileDialog);
  lObjectTypes.Add(TSaveTextFileDialog);
  lObjectTypes.Add(TFontDialog);
  lObjectTypes.Add(TColorDialog);
  lObjectTypes.Add(TPrintDialog);
  lObjectTypes.Add(TPrinterSetupDialog);
  lObjectTypes.Add(TFindDialog);
  lObjectTypes.Add(TReplaceDialog);
  lObjectTypes.Add(TPageSetupDialog);

  // Internet
  lObjectTypes.Add(TWebDispatcher);
  lObjectTypes.Add(TPageProducer);
  lObjectTypes.Add(TDataSetTableProducer);
  lObjectTypes.Add(TDataSetPageProducer);
  lObjectTypes.Add(TSQLQueryTableProducer);
  lObjectTypes.Add(TXMLDocument);
  lObjectTypes.Add(TWebBrowser);

  // Data Controls
  lObjectTypes.Add(TDBGrid);
  lObjectTypes.Add(TDBNavigator);
  lObjectTypes.Add(TDBText);
  lObjectTypes.Add(TDBEdit);
  lObjectTypes.Add(TDBMemo);
  lObjectTypes.Add(TDBImage);
  lObjectTypes.Add(TDBListBox);
  lObjectTypes.Add(TDBComboBox);
  lObjectTypes.Add(TDBCheckBox);
  lObjectTypes.Add(TDBRadioGroup);
  lObjectTypes.Add(TDBLookupListBox);
  lObjectTypes.Add(TDBLookupComboBox);
  lObjectTypes.Add(TDBRichEdit);
  lObjectTypes.Add(TDBCtrlGrid);
  lObjectTypes.Add(TDBChart);

  // Data Access
  lObjectTypes.Add(TDataSource);
  lObjectTypes.Add(TXMLTransform);
  lObjectTypes.Add(TXMLTransformProvider);
  lObjectTypes.Add(TXMLTransformClient);
  lObjectTypes.Add(TClientDataSet);
  lObjectTypes.Add(TDataSetProvider);

  // Indy Clients
  lObjectTypes.Add(TIdTCPClient);
  lObjectTypes.Add(TIdUDPClient);
  lObjectTypes.Add(TIdCmdTCPClient);
  lObjectTypes.Add(TIdIPMCastClient);
  lObjectTypes.Add(TIdIcmpClient);
  lObjectTypes.Add(TIdDayTime);
  lObjectTypes.Add(TIdDayTimeUDP);
  lObjectTypes.Add(TIdDICT);
  lObjectTypes.Add(TIdDNSResolver);
  lObjectTypes.Add(TIdEcho);
  lObjectTypes.Add(TIdEchoUDP);
  lObjectTypes.Add(TIdFinger);
  lObjectTypes.Add(TIdFSP);
  lObjectTypes.Add(TIdFTP);
  lObjectTypes.Add(TIdGopher);
  lObjectTypes.Add(TIdHTTP);
  lObjectTypes.Add(TIdIdent);
  lObjectTypes.Add(TIdIMAP4);
  lObjectTypes.Add(TIdIRC);
  lObjectTypes.Add(TIdLPR);
  lObjectTypes.Add(TIdNNTP);
  lObjectTypes.Add(TIdPOP3);
  lObjectTypes.Add(TIdQOTD);
  lObjectTypes.Add(TIdQOTDUDP);
  lObjectTypes.Add(TIdRexec);
  lObjectTypes.Add(TIdRSH);
  lObjectTypes.Add(TIdSMTP);
  lObjectTypes.Add(TIdSMTPRelay);
  lObjectTypes.Add(TIdSNMP);
  lObjectTypes.Add(TIdSNPP);
  lObjectTypes.Add(TIdSNTP);
  lObjectTypes.Add(TIdSysLog);
  lObjectTypes.Add(TIdSystat);
  lObjectTypes.Add(TIdSystatUDP);
  lObjectTypes.Add(TIdTelnet);
  lObjectTypes.Add(TIdTime);
  lObjectTypes.Add(TIdTimeUDP);
  lObjectTypes.Add(TIdTrivialFTP);
  lObjectTypes.Add(TIdUnixTime);
  lObjectTypes.Add(TIdUnixTimeUDP);
  lObjectTypes.Add(TIdWhoIs);

  // Indy Servers
  lObjectTypes.Add(TIdUDPServer);
  lObjectTypes.Add(TIdCmdTCPServer);
  lObjectTypes.Add(TIdSimpleServer);
  lObjectTypes.Add(TIdTCPServer);
  lObjectTypes.Add(TIdChargenServer);
  lObjectTypes.Add(TIdChargenUDPServer);
  lObjectTypes.Add(TIdDayTimeServer);
  lObjectTypes.Add(TIdDayTimeUDPServer);
  lObjectTypes.Add(TIdDICTServer);
  lObjectTypes.Add(TIdDISCARDServer);
  lObjectTypes.Add(TIdDiscardUDPServer);
  lObjectTypes.Add(TIdDNSServer);
  lObjectTypes.Add(TIdECHOServer);
  lObjectTypes.Add(TIdEchoUDPServer);
  lObjectTypes.Add(TIdFingerServer);
  lObjectTypes.Add(TIdFTPServer);
  lObjectTypes.Add(TIdGopherServer);
  lObjectTypes.Add(TIdHTTPProxyServer);
  lObjectTypes.Add(TIdHTTPServer);
  lObjectTypes.Add(TIdIdentServer);
  lObjectTypes.Add(TIdIMAP4Server);
  lObjectTypes.Add(TIdIPMCastServer);
  lObjectTypes.Add(TIdIRCServer);
  lObjectTypes.Add(TIdMappedFTP);
  lObjectTypes.Add(TIdMappedPOP3);
  lObjectTypes.Add(TIdMappedPortTCP);
  lObjectTypes.Add(TIdMappedPortUDP);
  lObjectTypes.Add(TIdMappedTelnet);
  lObjectTypes.Add(TIdNNTPServer);
  lObjectTypes.Add(TIdPOP3Server);
  lObjectTypes.Add(TIdQOTDServer);
  lObjectTypes.Add(TIdQotdUDPServer);
  lObjectTypes.Add(TIdRexecServer);
  lObjectTypes.Add(TIdRSHServer);
  lObjectTypes.Add(TIdSMTPServer);
  lObjectTypes.Add(TIdSocksServer);
  lObjectTypes.Add(TIdSyslogServer);
  lObjectTypes.Add(TIdSystatServer);
  lObjectTypes.Add(TIdSystatUDPServer);
  lObjectTypes.Add(TIdTelnetServer);
  lObjectTypes.Add(TIdTimeServer);
  lObjectTypes.Add(TIdTimeUDPServer);
  lObjectTypes.Add(TIdTrivialFTPServer);
  lObjectTypes.Add(TIdWhoIsServer);

  // Indy I/O Handlers
  lObjectTypes.Add(TIdIOHandlerStack);
  lObjectTypes.Add(TIdIOHandlerStream);
  lObjectTypes.Add(TIdServerIOHandlerStack);
  lObjectTypes.Add(TIdServerIOHandlerSSLOpenSSL);
  lObjectTypes.Add(TIdSSLIOHandlerSocketOpenSSL);

  // Indy Misc
  lObjectTypes.Add(TIdSocksInfo);
  lObjectTypes.Add(TIdAntiFreeze);
  lObjectTypes.Add(TIdSchedulerOfThreadDefault);
  lObjectTypes.Add(TIdSchedulerOfThreadPool);
  lObjectTypes.Add(TIdThreadComponent);
  lObjectTypes.Add(TIdConnectThroughHttpProxy);
  lObjectTypes.Add(TIdCompressorZlib);
  lObjectTypes.Add(TIdCookieManager);
  lObjectTypes.Add(TIdEncoderMIME);
  lObjectTypes.Add(TIdEncoderUUE);
  lObjectTypes.Add(TIdEncoderXXE);
  lObjectTypes.Add(TIdEncoderQuotedPrintable);
  lObjectTypes.Add(TIdDateTimeStamp);
  lObjectTypes.Add(TIdDecoderMIME);
  lObjectTypes.Add(TIdDecoderUUE);
  lObjectTypes.Add(TIdDecoderXXE);
  lObjectTypes.Add(TIdDecoderQuotedPrintable);
  lObjectTypes.Add(TIdIPWatch);
  lObjectTypes.Add(TIdIPAddrMon);
  lObjectTypes.Add(TIdMailBox);
  lObjectTypes.Add(TIdMessage);
  lObjectTypes.Add(TIdMessageDecoderMIME);
  lObjectTypes.Add(TIdMessageEncoderMIME);
  lObjectTypes.Add(TIdMessageDecoderYenc);
  lObjectTypes.Add(TIdMessageEncoderYenc);
  lObjectTypes.Add(TIdNetworkCalculator);
  lObjectTypes.Add(TIdSyslogMessage);
  lObjectTypes.Add(TIdUserManager);
  lObjectTypes.Add(TIdVCard);

  // Indy SASL
  lObjectTypes.Add(TIdSASLAnonymous);
  lObjectTypes.Add(TIdSASLCRAMMD5);
  lObjectTypes.Add(TIdSASLExternal);
  lObjectTypes.Add(TIdSASLLogin);
  lObjectTypes.Add(TIdSASLOTP);
  lObjectTypes.Add(TIdSASLPlain);
  lObjectTypes.Add(TIdSASLSKey);
  lObjectTypes.Add(TIdUserPassProvider);



  lObjectTypes.Add(TMainMenu);
  lObjectTypes.Add(TGridPanel);
  lObjectTypes.Add(TDrawGrid);
  lObjectTypes.Add(TLabel);
  lObjectTypes.Add(TBitBtn);
  lObjectTypes.Add(TImage);
  lObjectTypes.Add(TApplicationEvents);
  lObjectTypes.Add(TTabSet);
  lObjectTypes.Add(TFlowPanel);
  lObjectTypes.Add(TProgressBar);
  lObjectTypes.Add(TMonthCalendar);
  lObjectTypes.Add(TAdvStringGrid);
  lObjectTypes.Add(TMoneyEdit);
  lObjectTypes.Add(TDirectoryListBoxEx);
  lObjectTypes.Add(TFileListBoxEx);
  lObjectTypes.Add(TAdvDateTimePicker);
  lObjectTypes.Add(TPageControl);
  lObjectTypes.Add(TAdvSmoothDatePicker);
  lObjectTypes.Add(TPaintBox);
  lObjectTypes.Add(TMediaPlayer);
  lObjectTypes.Add(TOleContainer);
  lObjectTypes.Add(TCoolBar);

  // Indy
  lObjectTypes.Add(TIdSSLIOHandlerSocketOpenSSL);
  lObjectTypes.Add(TIdHTTPServer);
  lObjectTypes.Add(TIdHTTP);

  // REST Components
  lObjectTypes.Add(TRESTClient);
  lObjectTypes.Add(TRESTRequest);
  lObjectTypes.Add(TRESTResponse);
  lObjectTypes.Add(TNetHTTPClient);
  lObjectTypes.Add(TSimpleAuthenticator);
  lObjectTypes.Add(TOAuth2Authenticator);
  lObjectTypes.Add(TOAuth1Authenticator);

  // FireDac
  lObjectTypes.Add(TFDConnection);
  lObjectTypes.Add(TFDQuery);
  lObjectTypes.Add(TFDManager);
  lObjectTypes.Add(TFDMemTable);
  lObjectTypes.Add(TFDMemTable);
  lObjectTypes.Add(TFDStoredProc);
  lObjectTypes.Add(TFDMetaInfoQuery);
  lObjectTypes.Add(TFDLocalSQL);
  lObjectTypes.Add(TFDPhysMySQLDriverLink);
  lObjectTypes.Add(TFDPhysMSAccessDriverLink);
  lObjectTypes.Add(TFDPhysMSSQLDriverLink);

  // DBGo
  lObjectTypes.Add(TADOConnection);
  lObjectTypes.Add(TADOConnection);
  lObjectTypes.Add(TADOCommand);
  lObjectTypes.Add(TADODataSet);
  lObjectTypes.Add(TADOTable);
  lObjectTypes.Add(TADOQuery);
  lObjectTypes.Add(TADOStoredProc);
  lObjectTypes.Add(TADOQuery);

  lObjectTypes.Add(TWebBrowser);
  lObjectTypes.Add(TOpenDialog);
  lObjectTypes.Add(TSaveDialog);
  lObjectTypes.Add(TGauge);
  lObjectTypes.Add(TAbZipKit);

  lObjectTypes.Add(TJvMemoryData);
  lObjectTypes.Add(TAnimate);
  lObjectTypes.Add(TBluetoothLE);
  lObjectTypes.Add(TBeacon);
  lObjectTypes.Add(TNotificationCenter);

  lObjectTypes.Add(TChart);
  lObjectTypes.Add(TDBChart);
  lObjectTypes.Add(TImageList);
  lObjectTypes.Add(TRichEdit);
  lObjectTypes.Add(TTreeView);
  lObjectTypes.Add(TToolBar);
  lObjectTypes.Add(TShellResources);
  lObjectTypes.Add(TTaskbar);

With a big long list of components, which forced the components to be included in the exe file. This doesn’t include any of the non standard components, so you would need to add them to the list as well.

1 Like

If both programs are yours, could you add an extractRTTI method in the loaded application, and call it via named pipes or similar, to request RTTI information?
That way the loaded app accesses its own properties via RTTI and the calling app can request the information it wants via the pipe or similar mechanism.

1 Like

Test Complete really pulls apart the executable to gather the data - way above what I am willing to do.

I am actually after interface definitions within the other application, so making a list is a cool idea but won’t really work.

I do like the idea of having a pipe to request the information… Will definitely thinking about this a bit more.

Here is a few other things I found, looking at reverse engineering existing programs.

There is also potential to use something like DelphiDetours to inject code into a running process. You would still need to get the address of the objects of interest then though.