【发布时间】:2014-04-03 15:19:35
【问题描述】:
我一直在尝试访问在 Visual C# Express 2010 的 ROT 中注册的所有 Excel 2010 实例的 COM 对象。我在 http://adndevblog.typepad.com/autocad/2013/12/accessing-com-applications-from-the-running-object-table.html 上找到了一个代码,我对其进行了一些修改以返回所有可能的 @ 987654324@ 在运行对象表中注册的对象。代码:-
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices.ComTypes;
using System.Runtime.InteropServices;
using Excel = Microsoft.Office.Interop.Excel;
namespace APPROT
{
[ComVisible(true)]
class COMApp
{
[DllImport("Ole32.dll")]
public static extern int CreateBindCtx(
uint reserved,
out IBindCtx ppbc);
[DllImport("Ole32.dll")]
public static extern int GetRunningObjectTable(
int reserved,
out IRunningObjectTable prot);
[STAThread]
public static List<Excel.Application> GetRunningInstances()
{
string[] progIds = new string[] { "Excel.Application"};
List<string> clsIds = new List<string>();
// get the app clsid
foreach (string progId in progIds)
{
Type type = Type.GetTypeFromProgID(progId);
if (type != null)
clsIds.Add(type.GUID.ToString().ToUpper());
}
// get Running Object Table ...
IRunningObjectTable Rot = null;
GetRunningObjectTable(0, out Rot);
if (Rot == null)
return null;
// get enumerator for ROT entries
IEnumMoniker monikerEnumerator = null;
Rot.EnumRunning(out monikerEnumerator);
if (monikerEnumerator == null)
return null;
monikerEnumerator.Reset();
List<Excel.Application> instances = new List<Excel.Application>();
IntPtr pNumFetched = new IntPtr();
IMoniker[] monikers = new IMoniker[1];
// go through all entries and identifies app instances
while (monikerEnumerator.Next(1, monikers, pNumFetched) == 0)
{
object ComObject;
Rot.GetObject(monikers[0], out ComObject);
if (ComObject == null)
continue;
try
{
instances.Add((Excel.Application)ComObject);
}
catch {}
}
return instances;
}
}
}
但这只会返回excel第一个实例的Excel.Application对象。
我还尝试使用带有http://dotnet-snippets.de/snippet/laufende-com-objekte-abfragen/526(德语网站)上提到的代码的文件名访问对象,即使用GetRunningCOMObjectByName(string objectDisplayname),但是在获得COM对象之后,当我尝试将其转换为Excel.Application时,我得到以下错误:-
无法将“System.__ComObject”类型的 COM 对象转换为接口类型“Microsoft.Office.Interop.Excel.Application”。此操作失败,因为 IID 为“{000208D5-0000-0000-C000-000000000046}”的接口的 COM 组件上的 QueryInterface 调用因以下错误而失败:Cette interface n'est pas Prize en charge(来自 HRESULT 的异常: 0x80004002 (E_NOINTERFACE))。
我已尝试检查有问题的 dll,检查注册表是否由于 TypeLib 中 HKEY_CLASSES_ROOT 下存在不同的“版本”而导致 CLSID 发生冲突,尝试修复 Office 2010 女士,卸载旧版本的 Office (2003 ) 等来解决这个错误。但没有任何效果。我也尝试过使用Microsoft.VisualBasic 引用,然后使用Interaction.GetObject,但这也会产生同样的错误。
有什么想法吗?
我也试过https://stackoverflow.com/a/779710/2960814提到的后期绑定方法。 但这也可以访问 ROT 中的第一个 Excel 实例。
【问题讨论】:
-
Excel 是一个单实例应用程序。如果您再次启动它,它只会要求第一个实例打开文档。并退出。使用任务管理器的进程选项卡查看您正在运行的 Excel.exe 进程的数量。只有一个是正常的。
-
谢谢,这样就更清楚了。但有时我会打开两个 excel 实例,以便直观地比较文件。在一个实例下打开两个文件时,其中一些很难做到。这就是为什么我一直试图找出从所有实例中访问对象的方法。