连接到现有的 Excel 实例。

4

我正在尝试确定是否有一个实例的Excel正在运行并打开了特定的文件,如果是,则附加到它以便我可以控制该实例。

我已经搜索了一些内容,大部分来自this问题。它引用了另一个site,但不幸的是对我来说已经失效了,所以我无法阅读它。

到目前为止,我的代码如下:

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

到目前为止,我已经成功获取了我想要附加的实例的进程ID,但是在使用该ID时我感到困惑。

有什么建议吗?


你所发布的代码出了什么问题?还有,与你提供的链接回答相比,有哪些方面不足之处?(链接的博客可以在https://web.archive.org/web/20100420164139/http://blogs.officezealot.com/whitechapel/archive/2005/04/10/4514.aspx找到,但除了该回答中的内容外,没有太多其他信息。) - Ben Aaronson
同样重要的是:这是哪个版本的Excel?Excel 2013不幸地破坏了在早期版本中运行良好的东西。 - Ben Aaronson
我正在使用Office 2010,并且这是我的代码: Excel.Application existingExcel = (Excel.Application)System.Runtime.InteropServices.Marshal.GetActiveObject(process.Id); 它抛出一个错误:“无效的类字符串(HRESULT:0x800401F3(CO_E_CLASSSTRING))” 本质上,我想要做的事情是: exisitingExcel.Worksheets.add(); 使用我链接的答案只会抛出res变量为空的错误。 - Sean
1个回答

5

Marshal.GetActiveObject()方法不接受进程ID作为参数。您需要使用如下代码:

Marshal.GetActiveObject("Excel.Application");

请注意,这并不需要完全跟踪进程,只需要有一个进程即可。
如果您可以拥有多个进程并希望附加到特定进程,则会变得更加复杂。这就是其他问题的答案所在。
还有一篇很好的文章在http://blogs.msdn.com/b/andreww/archive/2008/11/30/starting-or-connecting-to-office-apps.aspx上,其中包含更详细的不同启动Excel的方式描述。请注意,并非所有方法都一定与Excel 2013最新版本兼容,因为对于所有Excel窗口只有一个进程的情况会使事情变得更加复杂。但是,对于您的目的,GetActiveObject解决方案应该是可以接受的。

2
你没有回答问题。启动Excel两次。打开任务管理器,你会发现有两个Excel在运行。在这种情况下,“GetActiveObject”只返回其中一个(最早的)实例。返回的实例可能不是OP想要的那个。 - Just a HK developer

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接