Get specific window handle using Office interop

Not sure why you need the handle to Word, but one way I've done this before is to actually change the Word window caption and search for it. I did this because I wanted to host the Word application inside a control, but that's another story. :)

  var word = new Microsoft.Office.Interop.Word.Application(); 
  word.Visible = true; 
  word.Activate();
  word.Application.Caption = "My Word";

  foreach( Process p in Process.GetProcessesByName( "winword" ) )
  {
    if( p.MainWindowTitle == "My Word" )
    {
      Debug.WriteLine( p.Handle.ToString() );
    }
  }

Once you got the handle, you can restore the caption if you like.


I'll leave the answer I've selected as correct, since it was what I found to work back when I wrote this. I've since needed to do do something similar for a different project and found that trying to update the application caption seemed to be less reliable (Office 2013 vs. 2010? Who knows...). Here's the new solution I've come up with that leaves window captions intact.

var startingProcesses = Process.GetProcessesByName("winword").ToList();

var word = new Microsoft.Office.Interop.Word.Application(); 

var allProcesses = Process.GetProcessesByName("winword").ToList();

var processDiff = allProcesses.Except(startingProcesses, new ProcessComparer());

var handle = processDiff.First().MainWindowHandle;

This uses the following custom comparer to ensure the processes match (found here).

class ProcessComparer : IEqualityComparer<Process>
{
    public bool Equals(Process x, Process y)
    {
        if (ReferenceEquals(x, y))
        {
            return true;
        }

        if (x == null || y == null)
        {
            return false;
        }

        return x.Id.Equals(y.Id);
    }

    public int GetHashCode(Process obj)
    {
        return obj.Id.GetHashCode();
    }
}