2012-09-14 2 views
0

У меня есть приложение в Delphi с сеткой.Чтение данных из сетки Delphi

Мне нужно создать другое приложение, которое должно

а) читать данные из сетки и б) записать данные в сеть,

I. е. подражать действиям человека.

Для того, чтобы прочитать данные из таблицы, я использую следующий код:

Procedure TForm1.Button1Click(Sender: TObject); 
type 
    PForm = ^TForm; 
    PClass = ^TClass; 
var 
    formPtr : PForm; 
    I: Integer; 
    msg : string; 
    windowHandle : HWND; 
begin 
    windowHandle := FindWindow('TForm1', 'FORMSSSSS'); 
    formPtr := PForm(GetVCLObjectAddr(windowHandle) + 4); 
    if (not Assigned(formPtr)) then Exit; 
    for I := 0 to formPtr^.ControlCount - 1 do // Error 
    begin 
    msg := msg + formPtr^.Controls[i].Name; 
    if formPtr^.Controls[i].Name = 'StringGrid1' then 
    begin 
     msg := TStringGrid(formPtr^.Controls[i]).Cells[1, 1]; 
    end; 

    end; 
    ShowMessage(msg); 
end; 


function GetVCLObjectAddr(AHandle: HWND): DWORD; 
var 
    pid: DWORD; 
begin 
    pid := 0; 
    GetWindowThreadProcessId(AHandle, pid); 
    if (pid =0) then 
    begin 
    Result := 0; 
    Exit; 
    end; 
    Result := GetPropW(AHandle, PWideChar(WideString(Format('Delphi%.8X', [PID])))) 
end; 

В соответствии с «Error» комментарий, возникает следующая проблема:

Проект Project1.exe поднял класс исключения EAccessViolation с сообщением «Доступ нарушение по адресу 0046C8C3 в модуле Project1.exe». Читайте адрес 01262984 '.

Когда я положил точку останова на эту строку и проверил значение выражения «formPtr ^» на вкладке «Часы», я получаю сообщение «Недоступное значение».

Как код должен быть изменен для чтения данных из сетки?

UPD:

Если изменить код к версии, приведенной ниже, проблема памяти исчезает. Но возникает другая проблема - контрольный счет равен нулю.

Procedure TForm1.Button1Click(Sender: TObject); 
var 
    formPtr : TForm; 
    I: Integer; 
    msg : string; 
    windowHandle : HWND; 
begin 
    windowHandle := FindWindow('TForm1', 'FORMSSSSS'); 
    formPtr := TForm(GetVCLObjectAddr(windowHandle) + 4); 
    if (not Assigned(formPtr)) then Exit; 
    for I := 0 to formPtr.ControlCount - 1 do 
    begin 
    msg := msg + formPtr.Controls[i].Name; 
    if formPtr.Controls[i].Name = 'StringGrid1' then 
    begin 
     msg := TStringGrid(formPtr.Controls[i]).Cells[1, 1]; 
    end;  
    end; 
    ShowMessage(msg); 
end; 
+3

Это не сработает. Два ваших процесса имеют изолированные адресные пространства. Адрес имеет смысл только в контексте процесса, которому принадлежит эта память. Вам нужно будет открыть интерфейс автоматизации, чтобы один процесс мог автоматизировать действия в другом процессе. –

+0

Есть ли примеры того, как это сделать? В принципе, мне нужно разработать приложение A (в Delphi или C# или C++), которое будет управлять (нажимать кнопки, читать/писать в/из текстовых полей) Delphi application B (которое я не могу изменить). –

+0

См. Также мое обновление исходного вопроса. –

ответ

1

Этот подход не может работать. Два ваших процесса имеют изолированные адресные пространства. Адрес и, следовательно, объект, имеют смысл только в контексте процесса, которому принадлежит этот адрес или объект. Вы можете вызывать методы только для объектов, которые находятся в вашем процессе.

+0

Да, но если вы поместите код (аналогичный приведенному выше) в DLL, а затем введите его в адресное пространство целевого приложения (как описано в http: //www.codeproject.com/Articles/4610/Three-Ways-to-Inject-Your-Code-in-Another-Proces), можно считывать значения TStringGrid. –

+0

Действительно так. Это точно моя точка зрения. Инъекция приводит ко всему коду, запущенному в том же процессе. –

Смежные вопросы