4
    proc.MainWindowTitle.Contains("e")

How does one get the window titles of all the current windows containing "e" open instead of just the Main Window using the "MainWindowTitle" and store them into a string array?

EDIT:

     string[] toClose = {proc.MainWindowTitle};
                for (int i = 0; i < toClose.Length; i++)
                {
                    string s = toClose[i];
                    int hwnd = 0;

                    hwnd = FindWindow(null, s);

                    //send WM_CLOSE system message
                    if (hwnd != 0)
                        SendMessage(hwnd, WM_CLOSE, 0, IntPtr.Zero);
First Second
  • 117
  • 2
  • 2
  • 10
  • Please read this related question (and the accepted answer). http://stackoverflow.com/questions/7268302/get-the-names-of-all-open-windows-not-process-name . I think that will help you. – HuorSwords Jul 26 '13 at 17:13
  • If you mean to retrieve all the windows owned by that process, you need to look into [EnumChildWindows](http://msdn.microsoft.com/en-us/library/windows/desktop/ms633494(v=vs.85).aspx), and call a [SendMessage](http://msdn.microsoft.com/en-us/library/windows/desktop/ms644950(v=vs.85).aspx) on them with the WM_GETTEXT Msg. – KappaG3 Jul 26 '13 at 18:05

3 Answers3

5

Code snippet

string[] result = new string[50];
int count = 0;
Process[] processes = Process.GetProcesses();
foreach(var process in processes)
{
    if (process.MainWindowTitle
               .IndexOf("e", StringComparison.InvariantCulture) > -1)
    {
        result[count] = process.MainWindowTitle;
        count++;
    }
}

Please review this question (and the accepted answer) that guides my answer.

Edit:

If I understand correctly, you want to retrieve de list of processes main window titles.

Analysing your code below, the toClose variable always store one title: the proc.MainWindowTitle value.

string[] toClose = { proc.MainWindowTitle };

You must retrieve each window title using the foreach statement of my original answer. Then, you must use the result variable in the proposed solution instead of toClose variable on your piece of code.

Community
  • 1
  • 1
HuorSwords
  • 2,225
  • 1
  • 21
  • 34
5
public static class MyEnumWindows
{
    private delegate bool EnumWindowsProc(IntPtr windowHandle, IntPtr lParam);

    [DllImport("user32")]
    private static extern bool EnumWindows(EnumWindowsProc lpEnumFunc, IntPtr lParam);

    [DllImport("user32.dll")]
    private static extern bool EnumChildWindows(IntPtr hWndStart, EnumWindowsProc callback, IntPtr lParam);

    [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
    public static extern IntPtr SendMessageTimeout(IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam, uint fuFlags, uint uTimeout, out IntPtr lpdwResult);

    private static List<string> windowTitles = new List<string>();

    public static List<string> GetWindowTitles(bool includeChildren)
    {
        EnumWindows(MyEnumWindows.EnumWindowsCallback, includeChildren ? (IntPtr)1 : IntPtr.Zero);
        return MyEnumWindows.windowTitles;
    }

    private static bool EnumWindowsCallback(IntPtr testWindowHandle, IntPtr includeChildren)
    {
        string title = MyEnumWindows.GetWindowTitle(testWindowHandle);
        if (MyEnumWindows.TitleMatches(title))
        {
            MyEnumWindows.windowTitles.Add(title);
        }
        if (includeChildren.Equals(IntPtr.Zero) == false)
        {
            MyEnumWindows.EnumChildWindows(testWindowHandle, MyEnumWindows.EnumWindowsCallback, IntPtr.Zero);
        }
        return true;
    }

    private static string GetWindowTitle(IntPtr windowHandle)
    {
        uint SMTO_ABORTIFHUNG = 0x0002;
        uint WM_GETTEXT = 0xD;
        int MAX_STRING_SIZE = 32768;
        IntPtr result;
        string title = string.Empty;
        IntPtr memoryHandle = Marshal.AllocCoTaskMem(MAX_STRING_SIZE);
        Marshal.Copy(title.ToCharArray(), 0, memoryHandle, title.Length);
        MyEnumWindows.SendMessageTimeout(windowHandle, WM_GETTEXT, (IntPtr)MAX_STRING_SIZE, memoryHandle, SMTO_ABORTIFHUNG, (uint)1000, out result);
        title = Marshal.PtrToStringAuto(memoryHandle);
        Marshal.FreeCoTaskMem(memoryHandle);
        return title;
    }

    private static bool TitleMatches(string title)
    {
        bool match = title.Contains("e");
        return match;
    }

}
sartoris
  • 816
  • 1
  • 7
  • 21
3

You will need to iterate through the process list (can be made with

Process[] processlist = Process.GetProcesses(); )

with foreach( Process in processlist )

and write the Process.MainWindowTitle to the array. Try that :)

SlimPDX
  • 713
  • 1
  • 6
  • 21
  • Tried this but it only returns one at a time not all – First Second Jul 26 '13 at 17:19
  • How are you adding it to the array? – SlimPDX Jul 26 '13 at 17:29
  • edited OP thats how I'm doing it, but it only gets one window at a time @MaxMarchuk – First Second Jul 26 '13 at 17:34
  • Make sure you are addding the end of the array and not overwriting the previous processes. That may be the problem? – SlimPDX Jul 26 '13 at 17:46
  • When you are iterating through the processlist in the ` foreach ` loop, are you adding the ` Process.MainWindowTitle ` to `array[array.count+1] ` ? adding it to array[array.count+1] will add it to the end of the array instead of overwriting what is already in it – SlimPDX Jul 26 '13 at 17:53
  • Sorry this might sound stupid but how do I go about adding 1 each time to the array? – First Second Jul 26 '13 at 17:55
  • No Problem. So you will want to delcare the array with ` string[] ProcessArray = new string[*Whatever size you want*]; ` and then insert the titles into that array with ` ProcessArray[ProcessArray.Count+1] = Process.MainWindowTitle; ` Try that :) – SlimPDX Jul 26 '13 at 18:02
  • let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/34254/discussion-between-maxmarchuk-and-first-second) – SlimPDX Jul 26 '13 at 18:30