来自VB6的.NET对象而不使用regasm.exe?

Posted

技术标签:

【中文标题】来自VB6的.NET对象而不使用regasm.exe?【英文标题】:.NET Object from VB6 without use of regasm.exe? 【发布时间】:2011-01-23 15:02:52 【问题描述】:

我工作的软件公司为学校构建软件,因此我们的客户端计算机通常被锁定,导致我们几乎无法在其上安装任何东西。

我们的旧系统主要基于一个(非常大的)MS Access 项目,因此它只需从本地文件夹运行即可解决访问问题。

我被赋予了将一些系统重新开发为 c# .NET 的任务 - 但是在过渡阶段,如果能够让 access 项目触发 .NET 事情,那就太好了。

我今天已经玩了几个小时的 com 互操作,但是使这些工作的唯一方法是使用 RegAsm.exe 注册它们 - 不幸的是,这不是客户端环境中的选项。

我尝试过 GetObject / CreateObject 但在引用 dll 或 tlb 文件时都不起作用,还有其他方法可以实现吗?

理想的解决方案是将 com interop dll 放在与 Access 项目相同的目录中。

是的,在任何人说之前,我就知道 MS Access 是邪恶的,只适合非常小的项目 - 但我 4 个月前才到这里......

马龙

【问题讨论】:

呃,你可能“知道”这一点,但事实并非如此。访问不是邪恶的,也不适合大型项目。它只需要适当地使用。您的 cmets 暗示甚至没有使用 Access,只有 Jet,因此这表明存在一定程度的混乱,可能会使您难以解决问题。也就是说,如果您甚至不了解所使用工具的关键区别,那么您就不太可能编写一个与您的理解水平相当模糊的工具一起使用的应用程序。 在下面阅读您的 cmets,您说您正在“使用 MS Access 项目,没有编译 VB6.exe”,所以我很困惑。它是 VB6 应用程序还是 Access 应用程序?如果是后者,您应该能够通过不在 Access 应用程序中创建引用并使用后期绑定来解决许多问题。但是您的 CreateObject cmets 往往暗示您的问题实际上是您无法注册所需的组件,因此这无济于事。我不清楚问题是什么,即是 .NET 问题还是 Access 问题。简而言之,没有足够的信息来真正提供答案。 @David 我认为问题在于 Marlon 想要从 Access 应用程序调用 C# 对象。但是他不能注册他的兼容 COM 的 C# 对象,因为用户没有权限。问题是是否有任何技术可以让 Access 项目调用 C# 对象,而无需管理员权限来注册 C# 对象。 无法为当前用户注册组件? 是的,我们不能有任何类型的安装过程。 【参考方案1】:

您可以在 Access 中托管 CLR:

添加对 mscoree 的引用(可能是 C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\mscoree.tlb)

Sub Main()
    Dim CORHost As New mscoree.CorRuntimeHost
    Dim Domain As Object
    Dim AssemblyFilename As String
    Dim Classname As String
    Dim Result As Object

    AssemblyFilename = "mscorlib"
    Classname = "System.Collections.ArrayList"

    CORHost.Start
    CORHost.CurrentDomain Domain
    Set Result = Domain.CreateInstance(AssemblyFilename, Classname).Unwrap()

    Result.Add "test"
    MsgBox Result.Count
End Sub

这绕过了使用注册表的需要。这样做的缺点是您必须对对象使用后期绑定。

您还可以添加对 mscorlib.tlb 的引用以获取 AppDomain 类和其他类的类型信息。

【讨论】:

您好,感谢您的帖子,听起来很有希望。我刚刚对其进行了测试,但是在将域对象传递给 CORHost.CurrentDomain 时出现“类型不匹配”错误。我查看了接口规范,它传递了一个指针而不是一个对象——vb6 会关心这个吗? (抱歉,我的 vb6 技能有限)。 如果您仍然得到与我更新的代码不匹配的类型,请尝试添加对 mscorlib.tlb 的引用并将 Domain 声明为 AppDomain。 您好,我仍然得到与该代码的类型不匹配,我还尝试添加对 mscorlib.tlb 的引用,但其中似乎没有“AppDomain”的定义。最接近的是 AppDomainManager 或 AppDomainSetup。 只有在你把“New”放在那里的情况下才会出现这种情况。 啊抱歉 - 是的,有效。非常感谢您提供此解决方案。【参考方案2】:

只要您的客户端系统是 Windows XP 或更高版本,您就可以选择使用Registration Free COM。这取代了在 XML 配置 manifest files 的系统注册表中使用 regasm(或用于本机 COM 服务器的 regsvr32)注册 COM 组件的需要。

这样你仍然可以使用标准的 CreateObject 调用来创建你的对象。

【讨论】:

我快速阅读了该教程,唯一的潜在问题是因为我们正在使用 MS Access 项目,没有编译 VB6.exe,所以我认为我无法编译清单与项目。不过我会进一步研究。 您可能需要将清单与 Access 主可执行文件放在一起。这有点冒险,您可能没有权限这样做。 您可以在运行时加载进程清单 -- msdn.microsoft.com/en-us/library/aa375259(VS.85).aspx【参考方案3】:

如果通过使用清单来使用我的 VB6 项目中的 .Net DLL。唯一的要求是 VB6 可执行文件和 .Net DLL 在同一个文件夹中。

我正在使用UMMM 工具在应用程序清单中自动创建依赖项。

您可以使用ActCtx.Manifest 属性动态加载适当的清单,以便无注册地访问 .Net 互操作 coclass。

【讨论】:

您能举个例子吗?例如我有:mycom.dll and mycom.tlb,我该如何配置?【参考方案4】:

你说你不能安装任何东西,但你能自己把必要的东西写进注册表吗?我认为 regasm 所做的就是将所有内容写入注册表,因此您可以在启动时从 VB 代码中有效地执行此操作(如果它不存在),然后您可能能够加载互操作程序集。

您可以使用process monitor 之类的工具查看运行 regasm 时写入注册表的内容。

我会确保您使用 -codebase 开关并为您的接口和 com 包装器的类明确定义 Guid。不这样做会导致我试图让 com 包装的 .net dll 正常工作的问题无穷无尽

【讨论】:

在 XP 和更高版本的 COM 对象可以在注册表的用户部分 (HKEY_CURRENT_USER) 中注册,您可能有权从用户帐户那里写入。您可能没有权限在全局范围内注册 COM 对象(在 HKEY_LOCAL_MACHINE 中)。您可以将 regasm 从 HKLM 转换为 HKCU regasm 有一个参数可以将注册表项创建为文件 - 无需使用进程监视器

以上是关于来自VB6的.NET对象而不使用regasm.exe?的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 ATL 创建 VB6 集合对象

VB.NET 从 DataTable 对象将表附加到数据库

vb6代码打开对话框而不使用commondialog控件

我可以将 .NET 5 COM 互操作对象与 VB6 连接起来吗?

运行外部进程而不冻结 vb6 中的主 UI

32 位 VB6 应用程序需要自动化 64 位 Outlook 发送电子邮件而不提示用户