2009-05-27 32 views
7

VB6 help on GetObject nói "Bạn không thể sử dụng GetObject để lấy tham chiếu đến một lớp được tạo bằng Visual Basic" (câu cuối cùng!). VB6 GUI của tôi cho thấy các đối tượng như một exe ActiveX, cho các thành phần khác để thao tác. Tôi muốn các thành phần khác kết nối với GUI đang chạy, thay vì bắt đầu một thể hiện mới của exe. Tôi đã tìm thấy bằng GetObject làm việc, nếu bạn sử dụng cú pháp sau:GetObject và VB6 ActiveX exe

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

Nó làm tôi lo lắng rằng sự giúp đỡ cho biết điều này không nên làm việc, mặc dù tôi đã làm khá nhiều thử nghiệm và đã không tìm thấy bất kỳ vấn đề cho đến nay. Bất kỳ chuyên gia COM ra có những người có thể cho tôi biết liệu tôi sẽ chạy vào các vấn đề xuống dòng? Và tôi có được OK với CreateObject không?

Cài đặt exe ActiveX là: nhóm luồng chỉ có một chuỗi. Lớp này có sự đa dạng của MultiUse. Có thể những cài đặt này đủ để ngăn chặn CreateObject bắt đầu một phiên bản mới của exe. Đúng không?

Trả lời

7

Tài liệu là khó hiểu, nhưng chính xác. Các trang MSDN bạn tham khảo giúp giải thích tại sao gọi GetObject của bạn không ném ra một lỗi:

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.

Đó là tinh tế, nhưng ngụ ý là

GetObject "", "ProjectName.ClassName 

thực sự là tương đương với

CreateObject "ProjectName.ClassName" 

Có nghĩa là, chuyển một chuỗi rỗng đến tham số đầu tiên của GetObject làm cho nó hoạt động chính xác như CreateObject, có nghĩa là nó sẽ tạo a Ví dụ mới của lớp, thay vì trả về tham chiếu đến một cá thể đã chạy.

Quay lại đoạn trích MSDN, nó đề cập rằng bỏ qua đối số đầu tiên là GetObject hoàn toàn sẽ gây ra GetObject để trả về tham chiếu đến một cá thể đã chạy, nếu có. Cuộc gọi như vậy sẽ như sau:

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

Tuy nhiên, nếu bạn cố thực hiện điều này, bạn sẽ gặp lỗi thời gian chạy ngay lập tức. Đây là trường hợp sử dụng mà tài liệu tham chiếu đến khi nó nói rằng GetObject không hoạt động với các lớp được tạo bằng VB6.

Lý do điều này không hoạt động là do cách GetObject thực hiện phép thuật của nó. Khi tham số đầu tiên được bỏ qua, nó cố gắng trả về một cá thể đối tượng hiện có bằng cách tham khảo Bảng đối tượng đang chạy (ROT), một bảng tra cứu toàn bộ máy có chứa các đối tượng COM. Vấn đề là các đối tượng phải được đăng ký rõ ràng trong Bảng đối tượng đang chạy bởi quá trình tạo chúng để có thể truy cập được vào các tiến trình khác - thời gian chạy VB6 không đăng ký các lớp ActiveX EXE trong ROT, vì vậy GetObject không có cách nào để lấy một tham chiếu đến một cá thể đã chạy.

+0

Câu trả lời hoàn hảo, cảm ơn bạn. Tôi luôn nói với mọi người về RT * M nên đây là hương vị của thuốc của tôi! GetObject (, "ProjectName.ClassName) gây ra lỗi 429", thành phần ActiveX không thể tạo đối tượng ".Tôi đoán nó thực sự là dự án của tôi và các thiết lập lớp đang ngăn cản nhiều trường hợp của EXE được tạo ra. – MarkJ

2

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

Bí quyết cần nhớ là trong EXE ActiveX, nó có thể được thiết lập để chỉ có một thể hiện của LIBRARY đang chạy. Đúng là bạn không thể với tới và chỉ nhổ một thể hiện nhất định của một lớp trên toàn bộ ranh giới quy trình. Tuy nhiên, ActiveX EXE có thể được thiết lập sao cho các biến GLOBAL có thể truy cập được bởi BẤT CỨ thể hiện của các lớp.

Cách chính xác để thực hiện việc này sẽ phức tạp hơn một chút.Bạn có thể sử dụng một EXE ActiveX như một EXE bình thường sự khác biệt chính là bạn phải sử dụng Sub Main. Bạn cũng có thể kiểm tra xem nó có chạy độc lập hay không. Bây giờ tôi giả định đây là trường hợp với ứng dụng của MarkJ.

Nếu đây là trường hợp bạn cần tạo một lớp ứng dụng và thiết lập nó khi nó được tạo (bằng cách sử dụng Class_Initialize), nó được điền bằng các biểu mẫu và bộ sưu tập hiện đang chạy.

Tôi khuyên bạn nên tạo một ActiveX DLL (không phải EXE) mà không có gì ngoài các lớp để triển khai dưới dạng giao diện. Thay vì đi tới

'Class ThisGUIApp 
Public MainForm as Form 

Bạn tạo giao diện có tất cả các thuộc tính và phương pháp cần thiết để truy cập các thành phần của biểu mẫu chính. Sau đó, bạn truy cập

'Class ThisGUIApp 
Public MainForm as IMainForm 

Private Sub Class_Initialize 
    Set MainForm = frmMyMainForm 
End Sub 

'Form frmMyMainForm 
Implements IMainForm 

Bạn làm điều này vì bạn có thể gửi Mẫu qua quá trình ứng dụng mọi thứ trở nên sôi nổi khi bạn cố gắng truy cập thành viên và điều khiển. Nếu bạn đã gán thông qua giao diện thì kết nối sẽ vững chắc hơn nhiều. Thêm vào đó nó tốt hơn tài liệu loại điều bạn đang cố gắng làm.

+0

+1. Cài đặt ActiveX exe là thread pool với chỉ một thread, và class có MultiUse instancing.Tôi nghĩ rằng điều này có nghĩa là chỉ có một instance chạy bao giờ.Tôi không vượt qua các form hoặc control trên toàn bộ quá trình, điều đó chắc chắn là flaky – MarkJ

+0

. miễn là bạn có biểu mẫu thực hiện một giao diện trong trường hợp đó nó được xử lý như một đối tượng ActiveX, tôi đã thực hiện điều này trong nhiều năm. –

Các vấn đề liên quan