4

I'm trying to determine whether or not an instance of Excel of running with a particular file open, and if so attach to it so I can control that instance.

I've searched around and the majority of what I've got have come from this question. It has a reference to another site, but unfortunately it's dead for me so I cannot read up on it.

My code so far is;

//Is Excel open?
if (Process.GetProcessesByName("EXCEL").Length != 0)
{
    Process[] processes = Process.GetProcesses();
    foreach (Process process in processes)
    {
        //Find the exact Excel instance
        if (process.ProcessName.ToString() == "EXCEL" && process.MainWindowTitle == ("Microsoft Excel - " + fileName))
        {
             //Get the process ID of that instance
             int processID = (int)Process.GetProcessById(process.Id).MainWindowHandle;

             //Attach to the instance...
             Excel.Application existingExcel = (Excel.Application)System.Runtime.InteropServices.Marshal.GetActiveObject(process.Id);                 
        }
    }
}

So far I've managed to get the process ID of the instance I want to attach to, but I'm lost when it comes to using that ID.

Any ideas on how to proceed?

Community
  • 1
  • 1
Sean
  • 49
  • 1
  • 3
  • What isn't working with the code you've posted so far? And what about the answer to the question you linked to isn't sufficient? (The linked blog can be found at https://web.archive.org/web/20100420164139/http://blogs.officezealot.com/whitechapel/archive/2005/04/10/4514.aspx but doesn't contain much more than what's in that answer) – Ben Aaronson May 14 '14 at 12:52
  • Also important: Which Excel version is this? Excel 2013 unfortunately breaks things which work fine with earlier verisons – Ben Aaronson May 14 '14 at 12:56
  • I'm using Office 2010, and it's this piece of code Excel.Application existingExcel = (Excel.Application)System.Runtime.InteropServices.Marshal.GetActiveObject(process.Id); It throws an error; "Invalid class string (Exception from HRESULT: 0x800401F3 (CO_E_CLASSSTRING))" Essentially I want to be able to do something like; exisitingExcel.Worksheets.add(); Using the answer that I linked to just throws an error the res variable being null. – Sean May 14 '14 at 13:15

1 Answers1

5

Marshal.GetActiveObject() doesn't take a process ID as a parameter. What you want is:

Marshal.GetActiveObject("Excel.Application");

Note that this doesn't require keeping track of the process at all, there just needs to be one.

It gets a lot more complicated if you can have multiple processes and want to attach to a specific one. That is where the answer to the other question comes in.

There is also a good article at http://blogs.msdn.com/b/andreww/archive/2008/11/30/starting-or-connecting-to-office-apps.aspx with a more full description of different ways of launching excel. Note that not all of them are necessarily up to date with Excel 2013, where having a single process for all Excel windows complicates things. For your purposes though, the GetActiveObject solution should be fine.

Ben Aaronson
  • 6,955
  • 2
  • 23
  • 38
  • 2
    You are not answering the question. Launch Excel twice. Go to Task Manager and you will find two Excel running. In this case, `GetActiveObject` returns only one (the oldest) of the instance running. The returned instance may not be the one the OP wants. – Just a HK developer Aug 25 '15 at 03:06