正在.NET中创建要在Excel中使用的COM类

本文关键字:COM NET 创建 正在 Excel | 更新日期: 2023-09-27 18:00:40

所以我觉得这是非常基本的,但无论出于什么原因,我都无法实现。

我有一个C#类,我想通过COM在Excel中使用。因此,当C#类注册到ROT(并且我的应用程序正在运行)时,当我在Excel中执行GetObject时,它应该会发现我的类是否有任何正在运行的实例,如果有,则返回该实例供Excel使用。我的问题是,我得到了一个429错误-它找不到类:(

我不想只发布一堵代码墙(除非有人要求),但我在.exe上做了一个regasm /codebase,它包含了我想在Excel中使用的COM可见类。我还指定了自己的GUID和ProgID,ProgID是我在Excel中用来获取对象的。

大多数代码都是由其他人编写的,我必须想办法修复它,所以以下代码片段我真的不知道它们是做什么的,但可能是有用的附加信息:

// this gets called before my class (MyApp) is made
RegistrationServices services = new RegistrationServices();
return services.RegisterTypeForComClients(typeof(MyApp), RegistrationClassContext.LocalServer, RegistrationConnectionType.MultipleUse);
// this gets called right after my class (MyApp) is made
if (MyApp == null) return;
Guid guid = typeof(MyApp).GUID;
RegisterActiveObject(MyApp, ref guid, 0, out _RegActiveObjectKey);

如果有用的话,这里只是一些关于这个类的信息:

[Guid("FDDBEB42-9E44-45fb-806B-EA535E2947F2")]
[ClassInterface(ClassInterfaceType.AutoDual)]
[ProgId("MyExe.MyApp")]
[ComVisible(true)]
public class MyApp : IDisposable
{
    // ...
}

EDIT:我甚至使用以下代码在ROT中明确注册了我的类:

IRunningObjectTable rot = null;
IMoniker pMoniker = null;
string filename = string.Empty;
int retVal = GetRunningObjectTable(0, out rot);
retVal = CreateFileMoniker(filename, out pMoniker);
retVal = rot.Register(1, _MyApp, pMoniker);

正在.NET中创建要在Excel中使用的COM类

我在我的.exe 上做了一个regasm/codebase

这并没有达到你所希望的效果。Regasm以独占方式注册进程内服务器,它们通常具有.dll扩展名。文件的扩展名为.exe,这一事实没有任何区别。CLR不会将它们与具有.dll扩展名的程序集区别对待。NET程序集有一个显示名称,与文件名相同。文件扩展名不是程序集全名的一部分,每当要求CLR加载程序集时,它将首先查找.exe,然后查找.dll。

所以你有一个鸡和蛋的问题,Excel不会加载你的程序集,直到它创建了一个你制作的[ComVisible]类的对象。不可避免的是,该对象永远不会出现在ROT中,您的程序集还从未注册过一个。

ROT通常只在两个独立的进程相互通信时才有用。换句话说,当您自己启动EXE时。在.NET中创建进程外服务器是一件非常尴尬的事情,你必须使用COM+托管并从ServicedComponent派生你的类。