Почему Control.FromHandle (IntPtr) возвращает null в одном подключенном процессе и возвращает действительный объект «Form»?в другом подключенном процессе? - PullRequest
5 голосов
/ 28 июня 2011

Я столкнулся с проблемой, связанной с извлечением всех элементов управления из некоторого подключенного процесса. Мой SpyDll успешно запущен в подключенный процесс, но когда я проверяю оператор

Control control = Control.FromHandle (MainWindowHandle), он возвращает ноль в управляющий объект, где «MainWindowhandle» - это просто собственный дескриптор главного окна этого подключенного процесса, который вы всегда берете из класса .NET «Процесс» после запуска этого процесса .

Но, как ни странно, случается, что в каком-то другом подключенном процессе, который является тем же приложением C # .NET, он возвращает действительный объект Main "WinForm".

Так почему же это не будет работать в вышеуказанном случае? Существуют ли исключения для правильного использования MainWindowHandle. В моем случае оба являются отдельными .NET управляемыми процессами, запрограммированными на C #. Любая конфигурация процесса должна специально поддерживаться при создании этого процесса?

С уважением Усман

Ответы [ 5 ]

1 голос
/ 18 июля 2011

Это связано с тем, что функция, которую вы вызываете "Control.FromHandle", использует хеш-таблицу для поиска экземпляра элемента управления из его дескриптора. Поэтому, когда вы вызываете этот метод для HWND, у которого нет экземпляра элемента управления, вы получите null.

Чтобы использовать HWND, вы должны использовать Win32 Messaging API через вызовы PInvoke. Например, вы можете использовать SendMessage , чтобы отправить сообщение WM_GETTEXT для запроса текста окна. Для некоторых из этих сообщений в Windows32 API Windowing имеются различные оболочки, такие как GetWindowText , которые переносят указанное выше сообщение.

1 голос
/ 29 июня 2011

Когда вы создаете элемент управления / форму с использованием WinForms, код WinForm автоматически сохраняет запись, которая сопоставляет дескриптор собственного окна с экземпляром C #.Когда элемент управления / форма уничтожается, эта запись затем удаляется.Поэтому все, что вызывает Control.FromChildHandle, - это поиск в списке записей, чтобы увидеть, имеет ли он соответствующий собственный дескриптор и, если да, возвращает связанный экземпляр C #.

Поэтому вы получите обратно записи C # только для экземпляров Control / Form, созданных из самой WinForms.Родные окна и собственный контроль от присоединения к другому процессу никогда не вернут запись.Вот почему это не работает для вас и никогда не будет, а также почему вы получаете верный класс при работе с приложением C #, которое использовало WinForms для создания окна.

0 голосов
/ 19 июля 2011

Для любого данного AppDomain нестатические члены типа T живут в сущности (экземпляр T). Статические члены типа T живут в другом отдельном объекте (сам тип T). Таким образом, тип или экземпляр T в одном домене приложений отличается от типа или экземпляра T в другом домене приложений. Это означает, что Control.FromHandle имеет смысл только в том случае, если возвращенный экземпляр находится в том же AppDomain, что и вызывающий метод, в противном случае он должен возвращать нуль.

Для работы с другим доменом приложения вам потребуется кодирование в стиле COM, что-то вроде (psuedocode):

runtimes = IClrMetaHost.EnumerateLoadedRuntimes(processHandle);
host = runtime[0].GetInterface( ICorRuntimeHost );
appdomains = host.EnumDomains();
appdomains[0].CallBack( () => dosomething(); );
0 голосов
/ 18 июля 2011

1.) Имейте в виду, что может быть несколько доменов приложений, и вы можете получить только управляющие объекты текущего домена приложения в текущем процессе. Также вы должны использовать правильную версию ruuntime afaik, но я не уверен в этом.

2.) Зачем вам в любом случае дескриптор управления, гораздо удобнее работать напрямую с нативными дескрипторами, вы даже можете использовать нативные функции из другого процесса, без внедрения dll. Если вам действительно нужны управляемые управляющие объекты, тогда замените Application.OpenForms collection вместо поиска по этому дескриптору!

0 голосов
/ 28 июня 2011

Вы рассматривали использование Control.FromChildHandle ?Он будет искать цепочку элементов управления, пока не найдет элемент управления, связанный с этим дескриптором.

В первом случае это может быть не прямой потомок.

...