gmnnn
gmnnn

Reputation: 339

EnumWindows doesn't work properly

I'm trying to take process names as a string from a listBox in a for loop and search for all windows of those applications. When I add items manually to the listBox, it works fine; but when I use an embedded text file to store and load process names to the listBox, it searches for all items but finds only the last one. For the other ones, Process.GetProcessesByName() throws an exception: Sequence contains no elements.

[DllImport("user32.dll")]
static extern bool EnumThreadWindows(int dwThreadId, EnumThreadDelegate lpfn, IntPtr lParam);

static IEnumerable<IntPtr> EnumerateProcessWindowHandles(int processId)
{
    var handles = new List<IntPtr>();
    foreach (ProcessThread thread in Process.GetProcessById(processId).Threads)
        EnumThreadWindows(thread.Id, (hWnd, lParam) => { handles.Add(hWnd); return true; }, IntPtr.Zero);

    return handles;
}

Searching algorithm:

public void searchForApplications()
{
  for (int i = 0; i < listBox1.Items.Count; i++)
  {
    try
    {
     foreach (var handle in EnumerateProcessWindowHandles
        (Process.GetProcessesByName(listBox1.Items[i].ToString()).First().Id))
        {
          StringBuilder message = new StringBuilder(1000);
          SendMessage(handle, WM_GETTEXT, message.Capacity, message);

          if (message.ToString().Length > 0)
          {
            addNewApplication(new Applications(message.ToString(), message.ToString(),
                   int.Parse(handle.ToString())));
          }
        }
    }
    catch (Exception ex)
    {
       MessageBox.Show(ex.Message);
    }
  }

} Thank you.

Upvotes: 0

Views: 708

Answers (1)

Steve Czetty
Steve Czetty

Reputation: 6228

If GetProcessesByName doesn't find any processes matching the name you passed in (check your list), then it will return an empty array and First() will throw an InvalidOperationException. You should probably use FirstOrDefault() and check for null before getting the Id:

// ...
var process = Process.GetProcessesByName(listBox1.Items[i].ToString()).FirstOrDefault();

if (process != null)
{
    foreach (var handle in EnumerateProcessWindowHandles(process.Id))
    {
        // ...
    }
}
// ...

Upvotes: 1

Related Questions