不使用regasm.exe从VB6创建.NET对象?

4
我所在的软件公司为学校开发软件,因此我们的客户机通常会被锁定,这使得我们几乎无法在其上安装任何东西。
我们的旧系统主要基于一个(非常大的)MS Access项目,因此它通过从本地文件夹运行来解决访问问题。
我被分配了将一些系统重新开发为c# .NET的任务 - 但是,在中间阶段具有让访问项目触发.NET事物的能力会很好。
我今天尝试了com interops几个小时,但据我所知,使它们工作的唯一方法是使用RegAsm.exe进行注册 - 不幸的是,这在客户环境中不是选项。
我尝试了GetObject / CreateObject,但引用dll或tlb文件时都无法工作,还有其他方法可以实现吗?
理想的解决方案是将com interop dll放置在Access项目的同一目录中。
是的,在有人说之前,我知道MS Access很邪恶,只适用于非常小的项目 - 但我只是在4个月前到达这里...
Marlon

嗯,你可能“知道”那个,但这不是真的。Access并不邪恶,也不适用于大型项目。它只需要被适当地使用。你的评论暗示着Access甚至没有被使用,只有Jet,这表明你存在一定程度的混淆,这很可能会使你难以解决问题。也就是说,如果你甚至不理解你正在使用的工具的关键区别,那么你很可能无法编写一个能够与这些工具一起工作的应用程序,因为你对这些工具的理解程度相当模糊。 - David-W-Fenton
阅读您在下面的评论中所说,您表示“正在使用MS Access项目工作,没有编译VB6.exe”,因此我感到困惑。这是一个VB6应用程序还是Access应用程序?如果是后者,您应该能够通过不在Access应用程序中创建引用并使用后期绑定来解决许多问题。但是,您的CreateObject注释倾向于表明您的问题实际上是无法注册所需组件,因此这将无济于事。而且我不清楚问题是什么,即它是.NET问题还是Access问题。简而言之,没有足够的信息来真正提供答案。 - David-W-Fenton
@David,我认为问题在于Marlon想从Access应用程序调用C#对象。但他无法注册他的兼容COM的C#对象,因为用户没有权限。问题是是否有任何技术可以让Access项目调用C#对象,而不需要管理员权限来获取C#对象的注册。 - MarkJ
当前用户无法注册组件吗? - David-W-Fenton
是的,我们不能有任何安装过程。 - Marlon
4个回答

6
你可以在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类和其他类的类型信息。


你好,感谢您的帖子,听起来非常有前途。我刚刚测试了一下,但是当将Domain对象传递给CORHost.CurrentDomain时,出现了“类型不匹配”的错误。我查看了接口规范,它传递的是指针而不是对象 - vb6会在意吗?(抱歉,我的vb6技能有限)。 - Marlon
如果您在使用我更新的代码时仍然遇到类型不匹配的问题,请尝试添加对mscorlib.tlb的引用,并将Domain声明为一个AppDomain。 - Foole
你好,我仍然在那段代码中遇到了类型不匹配的问题。我还尝试添加对mscorlib.tlb的引用,但似乎在其中没有“AppDomain”的定义。最接近的是AppDomainManager或AppDomainSetup。 - Marlon
只有在你输入了“New”时才应该出现这种情况。 - Foole

5
只要您的客户端系统是Windows XP或更高版本,就可以选择使用无需注册COM。这将使用XML配置清单文件替换在系统注册表中注册COM组件的需要,而无需使用regasm(或本机COM服务器的regsvr32)。
使用此方法,仍然可以使用标准的CreateObject调用来创建对象。

我快速浏览了一下那个教程,唯一的潜在问题是因为我们正在使用一个MS Access项目,没有VB6.exe被编译,所以我不认为我可以将清单与项目一起编译。不过我会进一步研究这个问题。 - Marlon
你可能需要将访问主可执行文件与清单放置在一起。这有一定的风险,并且您可能没有权限这样做。 - MarkJ
您可以在运行时加载进程清单 -- http://msdn.microsoft.com/zh-cn/library/aa375259(VS.85).aspx - wqw

1

我一直在使用清单来从我的VB6项目中使用.Net DLLs。唯一的要求是VB6可执行文件和.Net DLL位于同一个文件夹中。

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

您可以使用ActCtx.Manifest属性来动态加载适当的清单,以实现对.Net互操作Coclasses的无注册访问。


请提供一个示例,例如我有:mycom.dll和mycom.tlb,我该如何配置? - rubStackOverflow

0

你说你不能安装任何东西,但是你能否自己将必要的内容写入注册表呢?我认为regasm所做的就是将所有一些内容写入注册表,因此如果在启动时没有这些内容,你可以从你的VB代码中有效地完成这个过程,然后你可能就能够加载interop程序集了。

你可以使用像process monitor这样的工具来查看运行regasm时写入注册表的内容。

我会确保你使用了-codebase开关,并明确定义了你的接口和类的Guid,以便于com包装器的使用。不这样做会导致我在尝试让com包装的.net dll正常工作时遇到无尽的问题。


1
在XP及更高版本中,COM对象可以在注册表的用户部分(HKEY_CURRENT_USER)中注册,您可能拥有从用户帐户写入其中的权限。您可能没有全局注册COM对象的权限(在HKEY_LOCAL_MACHINE中)。您可以将regasm在HKLM中执行的操作转换为HKCU。 - MarkJ
regasm有一个参数,可以将注册表项创建为文件——无需使用进程监视器。 - Carl Onager

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