Question

I have a problem I'm trying to get a window's title by it's process name and I can't do it here s what I tried :

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

But the problem is that I can only get it only if the associated process does have a main window. How can I make it working ?

The main goal is that I've a method named BringToFront() But this method ask for a caption name which is "thenameofthePDF.pdf - Adobe Acrobat Pro (Yes, acrobat is running with an opened pdf) I would like to bring to front my Acrobat window.. but for this I need the name of the windows as my method is asking for the caption. Here is the entire code at the moment:

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();
    }
}
Was it helpful?

Solution 2

One possible solution is to enumerate all top-level windows and pick the one you are interested in. In your case this would be all windows with a class of AcrobatSDIWindow and a window title starting with your document name.

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);
        }
    }
}

OTHER TIPS

Did you read the manual, does the following apply?

A process has a main window associated with it only if the process has a graphical interface. If the associated process does not have a main window (so that MainWindowHandle is zero), MainWindowTitle is an empty string (""). If you have just started a process and want to use its main window title, consider using the WaitForInputIdle method to allow the process to finish starting, ensuring that the main window handle has been created. Otherwise, the system throws an exception.

If you dump them all out using GetProcesses() it appears that the window title will have 'Adobe Reader', prefixed by the name of the PDF if one is open. So you might need to do that and walk the array instead.

For example if I have UserManual.pdf open and I run the code below it displays UserManual.pdf - Adobe Reader on the console:

        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);
        }
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top