0

我有一个问题我试图通过它的进程名称来获取一个窗口的标题,但我不能在这里做我尝试过的事情:

Process[] p = Process.GetProcessesByName("Acrobat");
Console.WriteLine(p[0].MainWindowTitle);
Console.ReadLine();

但问题是,只有在关联进程确实有主窗口时,我才能得到它。我怎样才能让它工作?

主要目标是我有一个名为 BringToFront() 的方法但此方法要求标题名称为“thenameofthePDF.pdf - Adob​​e Acrobat Pro(是的,acrobat 正在使用打开的 pdf 运行)我想带到前面我的 Acrobat 窗口.. 但为此我需要窗口的名称,因为我的方法要求标题。这是目前的整个代码:

class Program
{
    [DllImport("User32.dll")]
    public static extern Int32 SetForegroundWindow(int hWnd);

    [DllImport("user32.dll")]
    public static extern int FindWindow(string lpClassName, string lpWindowName);

    private static void BringToFront(string className, string CaptionName)
    {
        SetForegroundWindow(FindWindow(className, CaptionName));
    }

    static void Main(string[] args)
    {
        // BringToFront("Acrobat", "mypdf.pdf - Adobe Acrobate Pro");
        Process[] p = Process.GetProcesses();
        foreach (var process in p)
        {
           Console.WriteLine(process.MainWindowTitle);
        }
        Console.ReadLine();
    }
}
4

3 回答 3

2

您是否阅读了手册,以下内容是否适用?

仅当进程具有图形界面时,进程才具有与之关联的主窗口。如果关联进程没有主窗口(因此 MainWindowHandle 为零),则 MainWindowTitle 为空字符串 ("")。如果您刚刚启动一个进程并希望使用其主窗口标题,请考虑使用 WaitForInputIdle 方法让该进程完成启动,确保已创建主窗口句柄。否则,系统会抛出异常。

于 2013-05-15T10:14:08.680 回答
1

一种可能的解决方案是枚举所有顶级窗口并选择您感兴趣的窗口。在您的情况下,这将是所有具有类的AcrobatSDIWindow窗口和以您的文档名称开头的窗口标题。

class Program
{
    public class SearchData
    {
        public string ClassName { get; set; }
        public string Title { get; set; }

        private readonly List<IntPtr> _result = new List<IntPtr>();
        public List<IntPtr> Result
        {
            get { return _result; }
        }
    }

    [DllImport("User32.dll")]
    public static extern Int32 SetForegroundWindow(IntPtr hWnd);

    [DllImport("user32.dll")]
    [return: MarshalAs(UnmanagedType.Bool)]
    private static extern bool EnumWindows(EnumWindowsProc lpEnumFunc, ref SearchData data);

    private delegate bool EnumWindowsProc(IntPtr hWnd, ref SearchData data);

    [DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
    public static extern int GetClassName(IntPtr hWnd, StringBuilder lpClassName, int nMaxCount);

    [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
    public static extern int GetWindowText(IntPtr hWnd, StringBuilder lpString, int nMaxCount);

    public static bool EnumProc(IntPtr hWnd, ref SearchData searchData)
    {
        var sbClassName = new StringBuilder(1024);
        GetClassName(hWnd, sbClassName, sbClassName.Capacity);
        if (searchData.ClassName == null || Regex.IsMatch(sbClassName.ToString(), searchData.ClassName))
        {
            var sbWindowText = new StringBuilder(1024);
            GetWindowText(hWnd, sbWindowText, sbWindowText.Capacity);
            if (searchData.Title == null || Regex.IsMatch(sbWindowText.ToString(), searchData.Title))
            {
                searchData.Result.Add(hWnd);
            }
        }
        return true;
    }

    static void Main(string[] args)
    {
        var searchData = new SearchData 
            { 
                ClassName = "AcrobatSDIWindow", 
                Title = "^My Document\\.pdf.*"
            };

        EnumWindows(EnumProc, ref searchData);

        var firstResult = searchData.Result.FirstOrDefault();
        if (firstResult != IntPtr.Zero)
        {
            SetForegroundWindow(firstResult);
        }
    }
}
于 2013-05-15T12:03:53.060 回答
0

如果您使用 GetProcesses() 将它们全部转储出来,则窗口标题似乎将带有“Adobe Reader”,如果打开了 PDF,则以 PDF 的名称为前缀。因此,您可能需要这样做并改为遍历数组。

例如,如果我打开 UserManual.pdf 并运行下面的代码,它会在控制台上显示UserManual.pdf - Adob​​e Reader :

        Process[] p = Process.GetProcesses();
        String Title = String.Empty;
        for (var i = 0; i < p.Length; i++)
        {
            Title = p[i].MainWindowTitle;

            if (Title.Contains(@"Adobe"))
                Console.WriteLine(Title);
        }
于 2013-05-15T10:28:47.183 回答