2009-05-27 132 views
7

VB6 help on GetObject说:“不能使用GetObject获取对使用Visual Basic创建的类的引用”(最后一句!)。我的VB6 GUI将对象公开为ActiveX exe,供其他组件操作。我希望其他组件连接到已经运行的GUI,而不是启动exe的新实例。我发现使用GetObject的做工作,如果你使用这个语法:GetObject和VB6 ActiveX exe

Set myobj = GetObject("", "ProjectName.ClassName") 

我担心的帮助说这不应该工作,虽然我已经做了相当多的测试,并没有发现任何迄今为止的问题。任何COM专家谁可以告诉我我是否会遇到问题?无论如何,我会用CreateObject吗?

ActiveX exe设置是:线程池只有一个线程。该班有多用途实例。可能这些设置足以防止CreateObject启动exe的新实例。那是对的吗?

回答

7

该文档令人困惑,但正确。您引用的MSDN页有助于解释为什么你GetObject电话不会引发错误:

If pathname [the first argument] is a zero-length string (""), GetObject returns a new object instance of the specified type. If the pathname argument is omitted, GetObject returns a currently active object of the specified type. If no object of the specified type exists, an error occurs.

这是微妙的,但含义是

GetObject "", "ProjectName.ClassName 

实际上相当于

CreateObject "ProjectName.ClassName" 

也就是说,将一个空字符串传递给第一个参数GetObject使其操作与CreateObject完全相同,这意味着它将创建一个新实例的类,而不是返回一个已经运行的实例的引用。

回到MSDN摘录,它提到将GetObject的第一个参数全部省略将导致GetObject返回对已存在的实例的引用。这样的电话是这样的:

GetObject , "ProjectName.ClassName" 'Note nothing at all is passed for the first argument' 

但是,如果你尝试这样做,你会立刻得到一个运行时错误。这是文档所指的不适用于使用VB6创建的类的用例。

这不起作用的原因是由于GetObject如何发挥其魔力。当省略第一个参数时,它会尝试通过查询运行对象表(ROT)(一个包含运行COM对象的机器范围查找表)来返回现有对象实例。问题是对象必须被创建它们的进程显式注册到运行对象表中,以便其他进程可以访问--VB6运行时不会在ROT中注册ActiveX EXE类,因此GetObject无法检索对已经运行的实例的引用。

+0

完美答案,谢谢。我总是告诉人们RT * M,所以这是我自己的药的味道! GetObject(,“ProjectName.ClassName)会导致错误429,”ActiveX组件无法创建对象“,我想这实际上是我的项目和类设置阻止创建EXE的多个实例 – MarkJ 2009-05-28 08:55:05

2

I want the other components to connect to the GUI that's already running, rather than start a new instance of the exe.

诀窍是要记住,在一个ActiveX EXE中,它可以被设置为只有一个LIBRARY实例正在运行。你无法到达,只是跨越过程边界拔取班级的某个实例是正确的。但是可以设置ActiveX EXE,以便任何类的任何实例都可以访问GLOBAL变量。

如何确切地做到这一点有点复杂。您可以使用ActiveX EXE作为正常的EXE,主要区别在于您必须使用Sub Main。您也可以检查它是否独立运行。现在我假设MarkJ的应用就是这种情况。

如果是这种情况,您需要创建一个应用程序类并进行设置,以便在创建时(通过使用Class_Initialize)使用当前正在运行的窗体和集合实例来填充应用程序类。

我强烈建议您创建一个ActiveX DLL(不是EXE),它只有类来实现为接口。而不是去

'Class ThisGUIApp 
Public MainForm as Form 

您创建一个接口,它具有访问mainform的元素所需的所有属性和方法。然后你去

'Class ThisGUIApp 
Public MainForm as IMainForm 

Private Sub Class_Initialize 
    Set MainForm = frmMyMainForm 
End Sub 

'Form frmMyMainForm 
Implements IMainForm 

你这样做,因为虽然你可以在应用程序发送表单事情变得靠不住的,当您尝试访问它的成员和控制。如果你通过一个接口进行分配,那么连接就会更加稳固。另外它更好地记录了你正在尝试做的事情的类型。

+0

+1。 ActiveX EXE设置是只有一个线程的线程池,并且该类有MultiUse实例。我认为这意味着只有一个实例运行。我没有通过进程边界的窗体或控件,这绝对是片状的。 – MarkJ 2009-09-24 09:11:28