delphi - 从外部应用程序将数据写入 Delphi TStringGrid

标签 delphi delphi-2009 dll-injection tstringgrid

我有一个用 Delphi 编写的遗留应用程序,需要构建一个机制

  1. 阅读和
  2. 写作

来自/到 TStringGrid 的数据。

我没有该应用程序的源代码,没有自动化接口(interface),供应商也不太可能提供该接口(interface)。

因此我创建了

  1. 一个 C++ DLL,用于注入(inject)
  2. 一个 Delphi DLL(由我编写)到
  3. 旧应用程序的地址空间。

DLL 2 可以访问旧应用程序内的 TStringGrid 实例,读取单元格值并将其写入调试日志。

阅读效果很好。但是,当我尝试使用类似

的调用将数据写入网格单元时
realGrid.Cells[1,1] := 'Test';

发生访问冲突。

代码如下:

procedure DllMain(reason: integer) ;
type
  PForm = ^TForm;
  PClass = ^TClass;
  PStringGrid = ^TStringGrid;
var
[...]
begin
  if reason = DLL_PROCESS_ATTACH then
  begin
    handle := FindWindow('TForm1', 'FORMSSSSS');

    formPtr := PForm(GetVCLObjectAddr(handle) + 4);

    if (not Assigned(formPtr)) then
    begin
      OutputDebugString(PChar('Not assigned'));
      Exit;
    end;

    form := formPtr^;

    // Find the grid component and assign it to variable realGrid
    [...]

    // Iterate over all cells of the grid and write their values into the debug log
    for I := 0 to realGrid.RowCount - 1 do
      begin
        for J := 0 to realGrid.ColCount - 1 do
          begin
            OutputDebugString(PChar('Grid[' + IntToStr(I) + '][' + IntToStr(J) + ']=' + realGrid.Cells[J,I]));
            // This works fine
          end;
      end;

    // Now we'll try to write data into the grid
    realGrid.Cells[1,1] := 'Test'; // Crash - access violation
  end;
end; (*DllMain*)

如何将数据写入 TStringGrid 而不会出现访问冲突问题?

最佳答案

这种方法根本行不通。目标可执行文件中有两个 VCL 实例。一份由目标应用程序拥有,一份由 DLL 拥有。这一个 VCL 实例太多了。如果使用完全相同版本的 Delphi 来构建目标应用程序和 DLL,您也许可以摆脱这种情况。

但是,您仍然有两个堆管理器在起作用。并且您的代码在不同的 VCL 实例之间传递堆分配的内存。您将在一个堆中分配并在另一堆中取消分配。这是行不通的,并且会导致访问冲突。

您正在将 DLL 堆中分配的字符串传递给使用目标应用程序堆的字符串网格对象。那是行不通的。

我认为,当 DLL 代码尝试释放由目标应用程序的堆管理器分配的 Cells[i,j] 的先前值时,就会发生访问冲突。

基本上你所尝试的方法是行不通的。您可以找到目标应用程序的 TStringGrid.SetCell 实现的地址,并伪造对其的调用。但您还需要找到目标应用程序的 GetMemFreeMem 等实现,并确保从 DLL 跨越到目标应用程序的所有动态内存都已分配并由目标应用程序的堆释放。你将有一份非常出色的工作来完成这项工作。当然,如果目标应用程序和 DLL 都使用共享内存管理器,那么您也许能够使这种方法发挥作用。

更简单的是伪造键盘输入。我个人会探讨使用 AutoHotKey 的可行性。

关于delphi - 从外部应用程序将数据写入 Delphi TStringGrid,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12454732/

相关文章:

delphi - 在 livebindings CustomFormat 中使用 Format

delphi - 更改来自 Delphi TWebBrowser 的 AJAX 调用的用户代理

Delphi,如何在两个不同的包中安装同名的组件

delphi - TIdHTTP 和 TLS SNI 不起作用

delphi - Variant 内容类型的字符串表示形式?

delphi - 在其他哪些 Delphi 版本中,Cardinals 的 for 循环失败了?

delphi - 将读锁升级为写锁时 TMultiReadExclusiveWriteSynchronizer 的行为

python-3.x - 使用 Python 3.2 CType 调用 CreateRemoteThread 时出现 Error_Invalid_Parameter 错误 57

c++ - 使用 CreateRemoteThread API 时如何修复 "LPVOID: unknown size"错误?

c++ - 如何修改运行时加载的 DLL 的导入地址表