如何使用进程ID获取Excel实例或Excel实例CLSID?

13
我正在使用C#,需要根据进程ID获取特定的Excel实例。我从另一个应用程序中获取所需实例的进程ID,但不知道该如何继续操作,也不知道如何根据进程ID获取正在运行的Excel实例。
我在网上进行了大量研究,但只看到了使用Marshal.GetActiveObject(...)或Marshal.BindToMoniker(...)的示例,但由于第一个方法返回在ROT中注册的第一个Excel实例而不是我需要的准确实例,因此我不能使用它;而第二个方法要求在尝试获取实例之前保存Excel文件。
另外,如果我能够使用进程ID获取所需Excel实例的CLSID,那么我可能能够调用。
GetActiveObject(ref _guid, _ptr, out objApp);

最终将返回我所需的 Excel 实例。


你能否给我提供一个使用 GetActiveObject 方法的示例? - Higune
3个回答

14

一旦您通过进程 ID 确定了进程,您可以获取 Process.MainWindowHandle,然后与 AccessibleObjectFromWindow API 一起使用,以访问该进程的 Excel 对象模型。

Andrew Whitechapel 的文章 Getting the Application Object in a Shimmed Automation Add-in 详细描述了这种技术及其示例代码。

该文章中对您最重要的代码从以下行开始:

int hwnd = (int)Process.GetCurrentProcess().MainWindowHandle

在你的情况下,可能会更像:

int excelId = 1234; // Change as appropriate!
int hwnd = (int)Process.GetProcessById(excelId).MainWindowHandle

其中'excelId'是您正在查找的进程ID号码。否则,代码应与文章中给出的基本相同。(忽略他的代码是针对插件编写的这一事实;这方面不会影响您的需求,因此请忽略它。)

如果您没有进程ID,则希望使用Process.GetProcessesByName,通过枚举每个进程并根据需要访问对象模型来获取每个Excel实例的控制权。

希望这能帮到您,

Mike


没问题,Vic,很高兴它对你有用。这不是一个容易解决的问题,也不是众所周知的,但是Andrew Whitechapel的文章涵盖得非常好。祝你好运! - Mike Rosenblum
4
文章已经下架,但这里有一份代码的Pastebin链接:http://pastebin.com/F7gkrAST。 - Simon Woker

2

ROT中的条目没有附带CLSID标签。从Register返回一个DWORD,用作Unregister的标识符。 我之前遇到过这个问题,唯一解决方法是在每个Excel中加载某种插件,您可以直接与该插件通信。


-3
using System.Diagnostics;

   var eProcess = from p in Process.GetProcessesByName("EXCEL")
                   where p.Id == 3700 //whatever Id you have...
                   select p;

    foreach (var process in eProcess)
        process.Kill();

这将获取所有名称为“EXCEL”的进程,其中进程ID等于特定值。


1
感谢您的快速回复, 问题在于我不想终止进程,我需要获取Excel实例以便处理它,更具体地说,我需要将一些信息粘贴到其中。 - Vic

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