FindWindow в C # (через pinvoke) находит нужный дескриптор окна, но не в нужных условиях.Как мне это исправить? - PullRequest
0 голосов
/ 31 декабря 2018

Я пытаюсь получить определенную ручку окна.Я искал решение в течение многих часов, и я понимаю, что мой вопрос звучит примерно так: FindWindow () не находит мое окно [C ++] Но это обсуждение не помогло.

Я пытался использовать как FindWindow (), так и FindWindowEx (), как эти два:

IntPtr SysPropWndHandler = FindWindow("#32770", "Параметри продуктивності");

IntPtr SysPropWndHandler = FindWindowEx(IntPtr.Zero, IntPtr.Zero, "#32770", "Параметри продуктивності");

Странная часть в том, что когда я запускаю программу, она запускает новый процесс для определенных программных настроек системы из папки system32.и он не может найти свою ручку в то же время запуска (если это правильно, так сказать).Я попытался приостановить его, чтобы дать ему время создать окно и назначить дескриптор, но это не помогает.Но!Если эта системная программа запускается первой, а затем я запускаю свою программу, она сразу же находит ее ручку.Два способа для этого «внешнего запуска»:

  1. Я запускаю системную программу перед запуском своей программы
  2. Я запускаю свою программу, которая запускает эту системную программу, затем я закрываю свою программу,Системная программа не закрывается.После этого я снова запускаю свою программу.

Но на самом деле я пытаюсь заставить мою программу сделать следующее:

  1. запустить системную программу (некоторые настройки производительности)
  2. скрыть окно
  3. изменить некоторые настройки через WinApi (вид эмуляции щелчка флажка)
  4. щелкнуть ОК
  5. закрыть

Поскольку мой код работает, по крайней мере, в некоторых условиях, похоже, что он не имеет ничего общего с кодированием, о котором шла речь в том же вопросе.Иначе это не сработало бы вообще.

Я пытался запустить его скрытно, но это не сработало.Я попробовал тот же код для блокнота для его отладки - он работает.

string prog_path = @"C:\Windows\System32\SystemPropertiesPerformance.exe";

Process process = new Process();
process.StartInfo.FileName = prog_path;
process.StartInfo.CreateNoWindow = true; // no need for that, but I tried with it and without it just in case it works
process.StartInfo.UseShellExecute = true;
process.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
process.Start();

В соответствии с документацией Microsoft вам нужно установить UseShellExecute на true, чтобы использовать StartInfo.WindowStyle = ProcessWindowStyle.Hidden (что я и сделал), но программа по-прежнему может игнорировать это.Похоже, это именно то, что там происходит.Но я попытался получить дескриптор окна Exect через Spy ++ и попытаться скрыть его - это работает, поэтому я могу манипулировать им оттуда и делать свое дело.Единственная проблема состоит в том, чтобы найти его дескриптор ...

Как мне найти этот дескриптор в этом случае?

PS

  • Windows 10 x64 Pro украинский (длядругие языки, в которых заголовок окна в коде не будет работать)
  • .NET Framework 4.7.2
  • Код находится внутри библиотеки классов .NET Framework, которая запускается из консольного приложения C #.

Ответы [ 2 ]

0 голосов
/ 31 декабря 2018

Другой подход заключается в использовании технологии UI Automation , встроенной в Windows.Например, этот пример консольного приложения должен работать.А поскольку он основан на событиях, ему не нужно использовать таймеры, которые могут зависеть от контекста:

public static void Main(string[] args)
{
    Automation.AddAutomationEventHandler(WindowPattern.WindowOpenedEvent, AutomationElement.RootElement, TreeScope.Children, (sender, e) =>
    {
        var element = sender as AutomationElement;
        if (element.Current.Name == "Параметры быстродействия")
        {
            Console.WriteLine("hwnd:" + element.Current.NativeWindowHandle);
        }
    });

    Process.Start("SystemPropertiesPerformance.exe");
    Console.ReadLine(); // wait ...
    Automation.RemoveAllEventHandlers(); // cleanup
}

Он отлично работает на моем компьютере с Windows 10 x64.Если это не работает, убедитесь, что ваша программа и SystemPropertiesPerformance.exe работают на одном уровне UAC .

0 голосов
/ 31 декабря 2018

Для меня это работает нормально (в Windows 7):

using System;
using System.Diagnostics;
using System.Text;
using System.Runtime.InteropServices;

namespace findwindow
{
    class Program
    {
        [DllImport("user32.dll", SetLastError = true)]
        static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
        [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        static extern int GetWindowText(IntPtr hWnd, StringBuilder lpString, int nMaxCount);
        public static void Main(string[] args)
        {
            Process.Start(new ProcessStartInfo(){FileName=@"C:\Windows\System32\SystemPropertiesPerformance.exe"});
            System.Threading.Thread.Sleep(100);
            IntPtr hwnd = FindWindow("#32770", "Параметры быстродействия");
            var sb = new StringBuilder(50);
            GetWindowText(hwnd, sb, 49);
            Console.WriteLine("hwnd:"+hwnd+", title:"+sb);
            Console.ReadKey(true);
        }
    }
}

Выходы:

hwnd:5636204, title:Параметры быстродействия

Попробуйте с этим кодом свой заголовок и скажите, работает ли он.

Также существует другой подход, как в этом ответе.

...