Питання Отримати екземпляр вікна з вікна ручки


Я можу отримати ручку вікна від запуску програм за допомогою такого коду.

foreach (ProcessModule module in process.Modules)
{
  if (module.ModuleName.Contains("PresentationFramework.dll") || module.ModuleName.Contains("PresentationFramework.ni.dll"))
  {
    IntPtr window = process.MainWindowHandle;
  }
}

Але я хочу отримати екземпляр Window з цього обробника. Це можливо?

Будь-яка швидка ідея, будь ласка


12
2018-02-25 11:02


походження


Ви маєте на увазі Window Handle? (без "r") Ви шукаєте дійсний об'єкт .NET? - Erno de Weerd
Я маю на увазі Window Handle. - Jawahar
Ви не можете отримати System.Windows.Window від HWND в іншому процесі. Хоча, що ви намагаєтесь зробити? Можливо, у вас є кілька способів зробити те, що ви намагаєтеся зробити в кінці. - Simon Mourier


Відповіді:


Спробуйте наступне:

IntPtr handle = process.MainWindowHandle;

HwndSource hwndSource = HwndSource.FromHwnd(handle);

Window = hwndSource.RootVisual as Window;

Оновлення:

Але це буде працювати тільки в тій же AppDomain, тому що в іншому випадку це означає, що ви можете поділитися об'єктом через різні AppDomains і навіть процеси, що, очевидно, неможливо.


11
2018-02-25 11:20



Це працює Але тільки для поточної програми. Я можу отримати вікно для поточної програми WPF. Інші кидають виключення NRE. HwndSource повертає нуль. Будь-яка інша допомога. - Jawahar
@Jawahar - Неможливо отримати доступ до об'єкта за межами поточного AppDoamin / Process (без використання Remoting). Див моє оновлення. - Pavlo Glazkov
Чи є якийсь інший спосіб, як використання некерованого коду, скажіть, використовуючи user32.dll. - Jawahar
@Jawahar - Це концептуальна проблема, не специфічна для .NET. Ви не можете поділитися тими ж об'єктами між процесами. Скажемо, що ви отримали екземпляр вікна з іншого процесу. Тепер запитайте себе, що має статися, якщо ви зміните деякі властивості цього вікна (наприклад, позицію)? Якщо це було можливо, тоді будь-яка програма могла б маніпулювати вікнами будь-якої іншої програми ... - Pavlo Glazkov
Хто-небудь має уявлення про те, як зробити зворотне? Мені потрібно отримати ручку IntPtr з існуючого об'єкта Window. - Dawid


У програмі WPF (або WinForms) в "вікні" є два "об'єкти" (тобто блоки пам'яті, що містять інформацію):

  1. Об'єкт системи вікна.
  2. Керовані об'єкти, які "обгортають" системний об'єкт.

Доступ до об'єкта системного вікна забезпечується через ручку вікна (typeof HWND у некерованому коді, IntPtr у керованому коді). Отримавши рукоятку вікна, яку ви вже отримали, ви можете маніпулювати цим вікном за допомогою API вікон API. Ви можете використовувати p / invoke для цього.

Доступ до керованого об'єкта, який знаходиться в купі процесу (або AppDomain у випадку керованого процесу), заборонено. Ця пам'ять "захищена" від інших процесів (1).

Єдиний спосіб, яким об'єкти можуть бути розподілені між процесами (або AppDomains), - це маршалювання, яке є спільним зусиллям обох процесів. Це стосується навіть багатьох методів Win32 API при доступі до вікна в іншому процесі. Не всі можливості доступні без спеціального сортування.

Зауважте, що, на відміну від WinForms, WPF (як правило) не використовує системні вікна для елементів керування. Якщо ваша мета - маніпулювати візуальним деревом в іншому процесі / домені WPF, то вам просто не вдається, якщо цей процес не надає інтерфейсу автоматизації.

(1) Хоча можна прочитати сиру пам'яті іншого процесу, об'єкти на керованій купі рухаються цілі. Навіть не могли їх навіть знайти, навіть якщо ви могли б якось призупинити нитку збирання сміття з цього процесу.


7
2018-02-25 18:41



+1 для "рухомих цілей", які "ніхто навіть ніколи не зможе знайти"! (мова вкрай барвиста в цілому, але це мене перемогла) - ivan_pozdeev