2009-05-27 71 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