Получение реального имени объекта (контрола)

Программирование на Visual Basic, главный форум. Обсуждение тем программирования на VB 1—6.
Даже если вы плохо разбираетесь в VB и программировании вообще — тут вам помогут. В разумных пределах, конечно.
Правила форума
Темы, в которых будет сначала написано «что нужно сделать», а затем просьба «помогите», будут закрыты.
Читайте требования к создаваемым темам.
visualman
Бывалый
Бывалый
 
Сообщения: 228
Зарегистрирован: 08.02.2002 (Пт) 19:06
Откуда: Russia

Получение реального имени объекта (контрола)

Сообщение visualman » 10.12.2013 (Вт) 22:32

Приветствую!

Много писано о получении реального (проектного) имени контролов по hWnd их окна. Так или иначе, все статьи (но в основном такие же просьбы, как и моя), приводят к этой статье: http://msdn.microsoft.com/en-us/library/ms996405.aspx. Я с этим кодом 3 дня ковыряюсь... и ни чего у меня не получается. То пустую строку возвращает, то непонятные числа, то переполнение стека (((.

Может есть у кого рабочий код? Поделитесь пожалуйста! Безумно надо! Громадное спасибо!
Причиной ошибок в коде служит давление со стороны руководства и жесткие временные рамки, им установленные.

Хакер
Телепат
Телепат
Аватара пользователя
 
Сообщения: 16478
Зарегистрирован: 13.11.2005 (Вс) 2:43
Откуда: Казахстан, Петропавловск

Re: Получение реального имени объекта (контрола)

Сообщение Хакер » 11.12.2013 (Ср) 10:22

visualman писал(а):Много писано о получении реального (проектного) имени контролов по hWnd их окна. Так или иначе, все статьи (но в основном такие же просьбы, как и моя), приводят к этой статье: http://msdn.microsoft.com/en-us/library/ms996405.aspx.

Эта статья о Windows Forms. А Windows Forms это:
Windows Forms — интерфейс программирования приложений (API), отвечающий за графический интерфейс пользователя и являющийся частью Microsoft .NET Framework.


Т.е. к VB это не имеет отношения.

Но способ получить имя VB-контрола по пожалуй. не только есть, но есть даже способ поуправлять им.
Посмотри вот это: viewtopic.php?f=54&t=42646

Насколько я помню, я начал писать утилиту, но так и не дописал. Идею могу подсказать.
—We separate their smiling faces from the rest of their body, Captain.
—That's right! We decapitate them.

visualman
Бывалый
Бывалый
 
Сообщения: 228
Зарегистрирован: 08.02.2002 (Пт) 19:06
Откуда: Russia

Re: Получение реального имени объекта (контрола)

Сообщение visualman » 11.12.2013 (Ср) 15:12

Хакер, спасибо за ссылку. Но меня инетесуют именно НЕ VBшные контролы.

Смысл: есть ПО автоматизации тестирования. Оно превосходно работает с софтом, написанным на С++, Delphi, VB. НО... с .NET объектами возникает проблема: ControlID у объектов не фиксированные, как в С++, например. Они для каждого запуска новые. И на них не завязаться при поиске объекта в новой инстансе, для получения их новых хэндлов.

У меня есть сорс на С#, данный нашим прогером. Сорс прекрасно выводит имена объектов. Вот его и пытаюсь на VB переписать. В нём ни чего сверхестественного, чистый API. А у меня не работает ( Прикладываю его.

Только мне в нём не понятно: Форма, написанная на С#, в ней он всё находит, но на точно такую же форму на VB - выдаёт кракозябры, вместо имён объектов ((

Спасибо!
Последний раз редактировалось visualman 11.12.2013 (Ср) 15:47, всего редактировалось 2 раз(а).
Причиной ошибок в коде служит давление со стороны руководства и жесткие временные рамки, им установленные.

visualman
Бывалый
Бывалый
 
Сообщения: 228
Зарегистрирован: 08.02.2002 (Пт) 19:06
Откуда: Russia

Re: Получение реального имени объекта (контрола)

Сообщение visualman » 11.12.2013 (Ср) 15:14

Сорс выложить не получается. Большой размер солюшена. Вот его код:

Код: Выделить всё
#include <Windows.h>

bool GetControlName(HWND controlHandle, wchar_t * buf, const int bufSize);

void main()
{
  HWND formHandle = FindWindow(0, "Form1");
  HWND firstChild = FindWindowEx(formHandle, 0, 0, 0);
  HWND secondChild = FindWindowEx(formHandle, firstChild, 0, 0);
  long dlgId = GetWindowLong(secondChild, GWL_ID);
  //PostMessage(formHandle, WM_COMMAND, MAKELONG(dlgId, BN_CLICKED), (LPARAM)firstChild);
  const int bufSize = 1024;
  wchar_t firstChildName[bufSize], secondChildName[bufSize];
  GetControlName(firstChild, firstChildName, bufSize);
  GetControlName(secondChild, secondChildName, bufSize);
  MessageBoxW(NULL, firstChildName, L"First button name", NULL);
  MessageBoxW(NULL, secondChildName, L"Second button name", NULL);
}

bool GetControlName(HWND controlHandle, wchar_t * buf, const int bufSize)
{
  DWORD ProcessId;
  SIZE_T NumRead;
  unsigned int GetName = RegisterWindowMessage("WM_GETCONTROLNAME");
  DWORD dwResult = GetWindowThreadProcessId(controlHandle, &ProcessId);
  HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS,false,ProcessId);
  LPVOID OtherMem = VirtualAllocEx(hProcess, 0, bufSize, MEM_COMMIT, PAGE_READWRITE);
  LPARAM lpOtherMem = reinterpret_cast<LPARAM>(OtherMem);
  unsigned int SendFlags = SMTO_ABORTIFHUNG | SMTO_BLOCK;
  LRESULT lResult = SendMessageTimeout(controlHandle, GetName, bufSize, lpOtherMem, SendFlags, 5000, &NumRead);
  BOOL bResult = ReadProcessMemory(hProcess, OtherMem, buf, bufSize, &NumRead);
  bResult = CloseHandle(hProcess);
  return bResult;
}
Причиной ошибок в коде служит давление со стороны руководства и жесткие временные рамки, им установленные.

visualman
Бывалый
Бывалый
 
Сообщения: 228
Зарегистрирован: 08.02.2002 (Пт) 19:06
Откуда: Russia

Re: Получение реального имени объекта (контрола)

Сообщение visualman » 11.12.2013 (Ср) 15:33

Глобальная цель задачи:

найти способ однозначной идентификации объекта в контейнере родителя, в разных сессиях работы этой программы. Т.е. нашли мы Button1 в софтине. Софтину выключили, запустили снова, и по какому то критерию (аля DLGITEMID) получили его новый hWnd. Без завязки на кэпшены, местоположение, имя класса или совокупность всего этого.

В случае НЕ .net приложений я работаю с ControlID и ни каких проблем не возникает.
Причиной ошибок в коде служит давление со стороны руководства и жесткие временные рамки, им установленные.

Хакер
Телепат
Телепат
Аватара пользователя
 
Сообщения: 16478
Зарегистрирован: 13.11.2005 (Вс) 2:43
Откуда: Казахстан, Петропавловск

Re: Получение реального имени объекта (контрола)

Сообщение Хакер » 11.12.2013 (Ср) 16:53

Свой код тоже выложи.
—We separate their smiling faces from the rest of their body, Captain.
—That's right! We decapitate them.

visualman
Бывалый
Бывалый
 
Сообщения: 228
Зарегистрирован: 08.02.2002 (Пт) 19:06
Откуда: Russia

Re: Получение реального имени объекта (контрола)

Сообщение visualman » 11.12.2013 (Ср) 17:02

Хакер писал(а):Свой код тоже выложи.

Через пару часиков. Он дома.
Причиной ошибок в коде служит давление со стороны руководства и жесткие временные рамки, им установленные.

Хакер
Телепат
Телепат
Аватара пользователя
 
Сообщения: 16478
Зарегистрирован: 13.11.2005 (Вс) 2:43
Откуда: Казахстан, Петропавловск

Re: Получение реального имени объекта (контрола)

Сообщение Хакер » 11.12.2013 (Ср) 17:36

Сишный код, например, ужасен. Создаёт утечку памяти в чужом процессе.
—We separate their smiling faces from the rest of their body, Captain.
—That's right! We decapitate them.

visualman
Бывалый
Бывалый
 
Сообщения: 228
Зарегистрирован: 08.02.2002 (Пт) 19:06
Откуда: Russia

Re: Получение реального имени объекта (контрола)

Сообщение visualman » 11.12.2013 (Ср) 23:44

Хакер, прошу, воздержись от 'горячих' высказываний....

Я правда, в С++ полный ноль. Сильно не ругай за то, что получилось на VB.

Сначала вот что покажу:
Код: Выделить всё
System.AccessViolationException: Попытка чтения или записи в защищенную память. Это часто свидетельствует о том, что другая память повреждена.
   в System.Runtime.InteropServices.Marshal.CopyToNative(Object source, Int32 startIndex, IntPtr destination, Int32 length)
   в System.Windows.Forms.Control.MarshalStringToMessage(String value, Message& m)
   в System.Windows.Forms.Control.WmGetControlName(Message& m)
   в System.Windows.Forms.Control.WndProc(Message& m)
   в System.Windows.Forms.ButtonBase.WndProc(Message& m)
   в System.Windows.Forms.Button.WndProc(Message& m)


Так крякнулась софтина на .NET, кнопу из которой я дёрнул.

А вот мой код. Прости, Господи...

Код: Выделить всё
Option Explicit

Private Declare Function FindWindow Lib "user32" Alias "FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName As String) As Long
Private Declare Function FindWindowEx Lib "user32" Alias "FindWindowExA" (ByVal hWnd1 As Long, ByVal hWnd2 As Long, ByVal lpsz1 As String, ByVal lpsz2 As String) As Long
Private Declare Function GetWindowLong Lib "user32" Alias "GetWindowLongA" (ByVal hwnd As Long, ByVal nIndex As Long) As Long
Private Declare Function RegisterWindowMessage Lib "user32" Alias "RegisterWindowMessageA" (ByVal lpString As String) As Long
Private Declare Function GetWindowThreadProcessId Lib "user32" (ByVal hwnd As Long, lpdwProcessId As Long) As Long
Private Declare Function OpenProcess Lib "kernel32.dll" (ByVal dwDesiredAccessas As Long, ByVal bInheritHandle As Long, ByVal dwProcId As Long) As Long
Private Declare Function VirtualAllocEx Lib "kernel32.dll" (ByVal hProcess As Long, lpAddress As Any, ByRef dwSize As Long, ByVal flAllocationType As Long, ByVal flProtect As Long) As Long
Private Declare Function SendMessageTimeout Lib "user32" Alias "SendMessageTimeoutA" (ByVal hwnd As Long, ByVal msg As Long, ByVal wParam As Long, ByVal lParam As String, ByVal fuFlags As Long, ByVal uTimeout As Long, lpdwResult As Long) As Long
Private Declare Function ReadProcessMemory Lib "kernel32" (ByVal hProcess As Long, ByVal lpBaseAddress As Long, ByVal lpBuffer As Long, ByVal nSize As Long, lpNumberOfBytesWritten As Long) As Long
Private Declare Function CloseHandle Lib "kernel32" (ByVal hObject As Long) As Long


Private Const MEM_COMMIT As Long = &H1000
Private Const PAGE_READWRITE As Long = &H4
Private Const GWL_ID = (-12)
Const PROCESS_ALL_ACCESS = &H1F0FFF
Private Const SMTO_ABORTIFHUNG = &H2
Private Const SMTO_BLOCK = &H1

Public Function GetControlName(ByVal CtrlHandle As Long, ByRef BufName As String, Optional ByVal BufSize As Long = 1024) As String
    Dim ProcessID As Long
    Dim NumRead As Long
    Dim GetName As Long
    Dim dwResult As Long
    Dim hProcess As Long
    Dim OtherMem As Long
    Dim lpOtherMem As Long
    Dim SendFlags As Long
    Dim lResult As Long
    Dim bResult As Boolean
   
    GetName = RegisterWindowMessage("WM_GETCONTROLNAME")
    dwResult = GetWindowThreadProcessId(CtrlHandle, ProcessID)
    hProcess = OpenProcess(PROCESS_ALL_ACCESS, False, ProcessID)
    OtherMem = VirtualAllocEx(hProcess, 0, BufSize, MEM_COMMIT, PAGE_READWRITE)
    lpOtherMem = OtherMem
    SendFlags = SMTO_ABORTIFHUNG Or SMTO_BLOCK
    lResult = SendMessageTimeout(CtrlHandle, GetName, BufSize, lpOtherMem, SendFlags, 5000, NumRead)
    bResult = ReadProcessMemory(hProcess, OtherMem, BufName, BufSize, NumRead)
    bResult = CloseHandle(hProcess)
End Function


Я вот эту строку не понял:
Код: Выделить всё
  LPARAM lpOtherMem = reinterpret_cast<LPARAM>(OtherMem);


Гугл выдал, что это преобразование данных. Но я не понял, во что нужно их преобразовывать. Так что просто присвоил.

VirtualAllocEx ни чего не вернул и потом упало тестовое приложение.

Спаси и сохрани...
Причиной ошибок в коде служит давление со стороны руководства и жесткие временные рамки, им установленные.

Хакер
Телепат
Телепат
Аватара пользователя
 
Сообщения: 16478
Зарегистрирован: 13.11.2005 (Вс) 2:43
Откуда: Казахстан, Петропавловск

Re: Получение реального имени объекта (контрола)

Сообщение Хакер » 12.12.2013 (Чт) 0:36

При том, второй аргумент VirtualAlloсEx объявлен как ... As Any

Эта строка должна:
OtherMem = VirtualAllocEx(hProcess, 0, BufSize, MEM_COMMIT, PAGE_READWRITE)
должна быть заменена на
OtherMem = VirtualAllocEx(hProcess, Byval 0&, BufSize, MEM_COMMIT, PAGE_READWRITE)

Либо же аргумент должен быть объявлен как ByVal ... As Long

В текущем варианте в функцию передаётся не сам ноль, а адрес нуля.


Остальное не смотрел.
—We separate their smiling faces from the rest of their body, Captain.
—That's right! We decapitate them.


Вернуться в Visual Basic 1–6

Кто сейчас на конференции

Сейчас этот форум просматривают: Google-бот, SemrushBot, Yandex-бот и гости: 31

    TopList