簡體   English   中英

C# 中的 FindWindow(通過 pinvoke)找到所需的窗口句柄,但不是在所需的條件下。 我如何解決它?

[英]FindWindow in C#(via pinvoke) finds desired window handle, but not in the desired conditions. How do I fix it?

我正在嘗試獲取某些窗口句柄。 我一直在尋找解決方案好幾個小時,我知道我的問題聽起來與這個問題相似: 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 (我這樣做了),但程序仍然可以選擇忽略它。 看起來這正是那里發生的事情。 但是我試圖通過 Spy++ 獲取 exec 窗口句柄並嘗試隱藏它 - 它有效,所以我可以從那里操縱它並做我的事情。 唯一的問題是找到它的句柄......

在這種情況下我如何找到那個句柄?

聚苯乙烯

  • Windows 10 x64 Pro 烏克蘭語(對於代碼中的窗口標題不起作用的其他語言)
  • .NET 框架 4.7.2
  • 代碼位於 .NET Framework 類庫中,該類庫從 C# 控制台應用程序啟動。

對我來說,這個工作正常(在 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:Параметры быстродействия

嘗試使用該代碼您的標題,然后說它是否有效。

還有一種不同的方法,如這個答案。

另一種方法是使用 Windows 內置的UI 自動化技術。 例如,這個示例控制台應用程序應該可以工作。 並且因為它是基於事件的,所以它不需要使用可以依賴於上下文的計時器:

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 級別運行。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM