简体   繁体   English

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

[英]How to get Excel instance or Excel instance CLSID using the Process ID?

I'm working with C#, I need to obtain a specific instance of excel by it's process ID; 我正在使用C#,我需要通过它的进程ID获取excel的特定实例; I get the Process ID of the instance that I need from another application but I don't know what else to do, I don't know how can I get a running instance of excel given his process ID. 我从另一个应用程序获取了我需要的实例的进程ID,但我不知道还能做什么,我不知道如何根据进程ID获取excel的运行实例。

I have researched a lot on the web, but I have only see examples of using Marshal.GetActiveObject(...) or Marshal.BindToMoniker(...), which I can't use since the first one returns the first Excel instance registered in the ROT and not precisely the one that I need, and the second one requires that you save the excel file before trying to get the instance. 我在网上已经研究了很多,但我只看到使用Marshal.GetActiveObject(...)或Marshal.BindToMoniker(...)的例子,我不能使用,因为第一个返回第一个Excel实例在ROT中注册而不是我需要的那个,第二个需要在尝试获取实例之前保存excel文件。

Also, if I where able to get the CLSID of the excel instance that I need, using the process ID, then I may be able to call 另外,如果我能够使用进程ID获取我需要的excel实例的CLSID,那么我可以调用

GetActiveObject(ref _guid, _ptr, out objApp);

that ultimately will return the excel instance that I need. 最终将返回我需要的excel实例。

Once you identify the process via the process id, you can get the Process.MainWindowHandle and then use that along with the AccessibleObjectFromWindow API to get access to the Excel object model for that process. 通过进程ID识别进程后,可以获取Process.MainWindowHandle ,然后将其与AccessibleObjectFromWindow API一起使用,以访问该进程的Excel对象模型。

The article Getting the Application Object in a Shimmed Automation Add-in by Andrew Whitechapel describes this technique in detail, along with sample code. Andrew Whitechapel 在一个Shimmed Automation Add-in中获取应用程序对象的文章详细描述了这种技术,以及示例代码。

The key code in that article for you begins at the line: 该文章中的关键代码从以下行开始:

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

Which in your case might look more like: 在您的情况下可能看起来更像:

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

where the 'excelId' is the process id number that you are looking for. 其中'excelId'是您要查找的进程ID号。 Otherwise, the code should be essentially the same as given in the article. 否则,代码应与文章中给出的代码基本相同。 (Ignore the fact that his code is written for an add-in; that aspect won't affect your needs here, so just ignore it.) (忽略他的代码是为加载项编写的事实;这方面不会影响你的需求,所以只需忽略它。)

If you do not have the process id, then you you would want to use Process.GetProcessesByName , whereby you could enumerate each one and grab control of each Excel instance with access to the object model, as needed. 如果您没有进程ID,那么您可以使用Process.GetProcessesByName ,根据需要,您可以枚举每个Excel并获取对象模型的控制权。

Hope this helps, 希望这可以帮助,

Mike 麦克风

The ROT entries are not tagged with a CLSID. ROT条目未标记为CLSID。 The ROT returns a DWORD from Register, which is used as a identifier for Unregister. ROT从Register返回一个DWORD,它用作取消注册的标识符。 I've run into this problem before and the only way I've solved it is to have some kind of add-in loaded into each Excel that you can communicate directly with. 我以前遇到过这个问题,我解决它的唯一方法是在每个Excel中加载一些可以直接与之通信的加载项。

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();

This gets all processes named "EXCEL" where the Process Id equals a specific value. 这将获得名为“EXCEL”的所有进程,其中进程ID等于特定值。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM