2010-09-21 5 views
6

Ich habe ein Projekt, die VB6 COMSVCSLib und eines des Verfahrens macht Anrufe COMSVCSLib des SharedPropertyGroupManager.CreatePropertyGroup vorbei LockMethod und Prozess als Parameter bezieht.Warum werden TypeLib-Enums in Visual Basic 6.0 nicht als Enums verfügbar gemacht?

Aufgeräumt VB6-Code:

Dim groupName  As String 
Dim spmMgr   As COMSVCSLib.SharedPropertyGroupManager 
Dim spmGroup  As COMSVCSLib.SharedPropertyGroup 

Dim bGroupExists As Boolean 

Set spmMgr = New COMSVCSLib.SharedPropertyGroupManager 

With spmMgr 
    Set spmGroup = .CreatePropertyGroup(groupName, LockMethod, Process, bGroupExists) 

End With 

Nachdem jetzt nicht mit VB6 seit mehreren Jahren gearbeitet, zuerst dachte ich, LockMethod und Verfahren waren Variablen oder Konstanten irgendwo anders innerhalb des Projekts definiert.

Nach ein wenig Forschung über den Objektbrowser fand ich heraus, dass sie beide als Konstanten in COMSVCSLib ausgesetzt waren.

Object Browser

Aber bei ihrer Definition suchen in OLE/COM-Objektkatalog, scheinen sie als Werte einer Enumeration definiert werden:

typedef enum { 
    LockSetGet = 0, 
    LockMethod = 1 
} __MIDL___MIDL_itf_autosvcs_0469_0002; 

Warum sind nicht IDL/TypeLib Aufzählungen von COMSVCSLib als Visual Basic 6.0 zur Verfügung gestellt werden?

Antwort

10

Haftungsausschluss: Ich bin kein Experte für IDL (Interface Definition Language, die die Sprache COM-Typen verwendet werden, definieren) oder die Microsoft IDL-Compiler (MIDL), aber ich kam zu den nachstehenden Schlussfolgerungen nach dem Spielen um mit der Typbibliothek für scrrun.dll, die ein ähnliches Problem mit enum hat. Einige dieser Informationen wurde von einem kurzen Blick auf diese DevX Artikel auf IDL und VB6 aufgelesen: IDL for VB Tutorial

VB6 die tatsächliche Enum erwartet einen Namen haben, nicht nur eine Enum, die typedef ist ‚zu einem Namen d. Der Name __MIDL___MIDL_itf_autosvcs_0469_0002 ist ein Platzhalter, da die ursprüngliche typelib den enum-Namen nicht in demselben typedef definiert, in dem die enum-Konstanten definiert sind.

Wenn Sie die Typbibliothek in OLE-Viewer ansehen, dann sieht die enum wahrscheinlich wie folgt aus:

typedef [public] __MIDL___MIDL_itf_autosvcs_0469_0002 LockModes; 

typedef enum { 
    LockSetGet = 0, 
    LockMethod = 1 
} __MIDL___MIDL_itf_autosvcs_0469_0002; 

Der erste typedef den öffentlichen Namen LockModes als Alias ​​für den automatisch generierten MIDL___MIDL_itf_autosvcs_0469_0002 Namen erstellt, die gegeben wurde die enum. Wenn die Bibliothek vom ursprünglichen Typ kompiliert wurde, generierte der Compiler midl den langen __MIDL-Namen für das ursprüngliche enum und automatisch erstellte einen Alias ​​typedef, der darauf zurückleitete.

Die ursprüngliche IDL definiert wahrscheinlich die Enum wie folgt aus:

typedef enum { 
    LockSetGet = 0, 
    LockMethod = 1 
} LockModes; 

Wenn der midl Compiler eine enum Definition geschrieben auf diese Weise verarbeitet, es einen Namen für die enum generiert automatisch (da es fehlt - es sollte erscheinen nach dem Schlüsselwort enum). Dies ist der Name __MIDL, den Sie sehen, wenn Sie die Typbibliothek in OLE Viewer anzeigen. Der midl Compiler generiert auch automatisch eine zweite typedef, die den typedef Namen automatisch generiert enum Namen.

Das Problem ist, dass VB6 Enum, die auf diese Weise erstellt werden, nicht verstehen kann. Er erwartet, dass alles in einem einzigen typedef sein (dh Sie enum einen Namen geben, sowie die Benennung der typedef):

typedef enum LocksMode { 
    LockSetGet = 0, 
    LockMethod = 1 
} LocksMode; 

IDL behandelt typedef ‚s die gleiche Art und Weise, dass C oder C++ tut: Sie don‘ t muss dem enum selbst einen Namen geben, denn der typedef hat schon einen Namen, aber du kannst dem enum einen Namen geben, wenn du es wählst. Mit anderen Worten, die typedef und die enum sind eigentlich zwei separate Entitäten. VB6 passiert, die typedef und die enum als zwei verschiedene, aber vage verwandte Dinge zu erkennen, so in Ihrem Fall sieht es typedef mit dem Namen __MIDL___MIDL_itf_autosvcs_0469_0002, und es sieht, dass dies ein Alias ​​für eine unbenannte enum ist, und es sieht auch eine typedef für LockModes, die ein öffentlicher Alias ​​für die anderen typedef ist.

Da die erste typedef öffentlich ist, wird im Objektbrowser ein Eintrag für LockModes angezeigt, und da es sich um einen Alias ​​für eine Enumeration handelt, werden die Enum-Konstanten auch im Objektbrowser angezeigt. Allerdings hat die tatsächliche enum selbst keinen Namen (so erhält es den funky automatisch generierten Namen im Browser zugewiesen), und VB6 kann die enum nicht verwenden, weil der automatisch generierte Name zufällig in ist VB6 (Namen mit doppelten Unterstrichen werden in VB6 automatisch ausgeblendet).

Um diesen letzten Punkt zu demonstrieren, wenn Sie diesen Code in Ihrem VB6 eingeben, wird Intellisense arbeiten und es wird kompilieren, aber offensichtlich ist es nicht sehr ideal:

MsgBox COMSVCSLib.[__MIDL___MIDL_itf_autosvcs_0469_0002].LockMethod 

Der Grund dieser Code funktioniert, weil Sie ist kann Namen in Klammern setzen, die normalerweise Syntaxfehler verursachen (z. B. Namen, die mit Unterstrichen beginnen), damit VB6 den normalerweise ungültigen Namen akzeptiert. Darüber hinaus funktioniert das Voranstellen der Konstanten mit dem automatisch generierten Namen mit Intellisense, weil es der tatsächliche Name ist, den VB6 mit der enum assoziiert (erinnern Sie sich an die andere typedef ist nur ein Alias ​​zurück zu diesem "echten", aber automatisch generierten Namen, und VB6 kann anscheinend nicht alle Teile zusammenfügen, um zu realisieren, dass beide Namen sich auf denselben beziehen enum).

Anstatt den lächerlich langen Namen wie oben beschrieben einzugeben, können Sie auch auf die Konstanten enum zugreifen, indem Sie ihnen den Namen der Bibliothek voranstellen. Beispiel: COMSVCSLib.LockMethod sollte funktionieren. Es ist mir weniger klar, warum das tatsächlich funktioniert, und ich bin nicht sicher, was passieren würde, wenn zwei verschiedene enum Konstanten mit dem gleichen Namen definieren.

Schließlich könnte dieses Problem eine andere Art und Weise beheben, indem Sie die IDL aus dem OLE-Viewer mit einer benutzerdefinierten IDL-Datei zu erstellen, in denen ersetzen Sie die vorhandenen enum typedefs mit einem einzigen typedef für jede enum, die einfach gibt sowohl die enum und die typedef den gleichen Namen (dh typedef enum LockModes { ... } LockModes;), aber da der OLE Viewer nicht unbedingt gültige IDL generiert, müssten Sie wahrscheinlich noch mehr zwicken, um es tatsächlich zu kompilieren. Wenn Sie dies zum Funktionieren bringen können, können Sie Ihre benutzerdefinierte .tlb von Ihrem VB6-Projekt (anstelle der COMSVCSLib-Bibliothek) referenzieren, und die enum funktioniert so, wie Sie es erwarten würden.

Wenn Sie diesen Weg gehen wollen, gibt es zwei weitere Werkzeuge, die Sie benötigen, die bereits auf dem Entwicklungscomputer installiert werden sollte (aber Sie können nach ihnen suchen müssen):

  • midl.exe: Diese Tool kann eine Typelib-Datei (* .tlb) aus einer .idl Datei erzeugen. So könnte man die IDL aus dem OLE-Viewer in den Editor kopieren, ändern Sie die Enum-Definitionen, wie oben beschrieben, speichern Sie sie als .idl Datei und übergeben es an midl.exe, um einen neuen typelib zu machen:

    midl my-custom-typelib.idl

  • regtlib.exe : Dieses Tool kann eine TLB-Datei, registriert die, wenn Sie es als Referenz zu Ihrem VB6 Projekt hinzufügen können erforderlich werden sollen:

    regtlib.exe my-custom-typelib.tlb

Das Erstellen einer benutzerdefinierten typelib ist jedoch wahrscheinlich übertrieben, und wie bereits erwähnt, kann es schwierig sein, eine kompilierbare IDL-Datei basierend auf der Ausgabe aus dem OLE-Viewer zu erhalten, da sie reverse-engineed IDL für die Typbibliothek anzeigt. nicht die ursprüngliche IDL.

+0

@wqw: Ich bin mir nicht sicher über alle technischen Details - diese Antwort basiert auf empirischen Tests. Wenn Sie beispielsweise die von OLE Viewer generierte IDL für scrrun.dll übernehmen und sie in eine neue Typbibliothek mit 'midl.exe' kompilieren, kann VB6 die Enumeration nur dann korrekt anzeigen, wenn Sie der enum _and_ the typedef einen Namen geben die IDL. Andernfalls sehen Sie den 'enum'-Namen im Objektbrowser, aber IntelliSense wird nicht korrekt funktionieren, und wenn Sie sich die enum-Konstanten im Objektbrowser ansehen, wird es sagen, dass die enum's Mitglied einer enum mit einem auto sind -generierter Name –

+0

Sie müssen nicht einmal eine neue Typbibliothek erstellen, um dies zu sehen: Fügen Sie einfach einen Verweis auf 'scrrun.dll' zu einem neuen VB6-Projekt hinzu, öffnen Sie dann den Objektbrowser und schauen Sie sich die' SpecialFolderConst'-Enumeration an. Ja, es wird im Objektbrowser angezeigt, und ja, die Konstanten sind dafür aufgelistet, aber wenn Sie zum Beispiel auf die 'SystemFolder'-Konstante klicken, sagt der Objektbrowser, dass es ein Mitglied von' Scripting .__ MIDL ___ MIDL_itf_scrun_0001_0000_0002' ist. Es sollte sagen, dass die Konstante ein Mitglied von 'Scripting.SpecialFolderConst' ist, aber die Art, wie die Typbibliothek definiert ist, ist nicht 100% kompatibel mit VB6. –

+0

Auch ich sage zu versuchen, meine Antwort ist perfekt (das ist, warum ich einen Disclaimer dort), aber soweit ich sagen kann, diese Erklärung passt zu tatsächlichen Tests. Ich habe eine neue Typbibliothek für sccrun.dll erstellt und die enum typedefs so geändert, dass sie enum-Namen zusätzlich zu den typedef-Namen enthält. Wenn ich diese Typbibliothek zu VB6 hinzufüge, werden die enum im Object Browser korrekt angezeigt aufgeführt als Mitglieder der richtigen Enumeration, und IntelliSense funktioniert ordnungsgemäß.Wenn ich jedoch die technischen Details falsch verstanden habe, könnten Sie eine Antwort mit den richtigen Informationen geben? –

1

Es ist als ein Enum ausgesetzt. Wählen Sie LockModes in der Klassenliste und werfen Sie einen Blick auf den unteren Informationsbereich. Du wirst sehen, dass es ein Enum ist. Oder Sie könnten in Ihrem Code LockModes. eingeben und Sie würden die zwei Optionen erhalten.

In der Objektanzeige wird jedes Element innerhalb einer Enumeration als konstanter Wert identifiziert, es handelt sich jedoch nicht um eine eigenständige Konstante. Standalone-Probleme werden separat aufgelistet, wenn Sie den Eintrag <globals> in der Klassenliste auswählen.

+0

Yeah ... Du hast Recht, dass es ein enum ist. Ich habe das im Objektbrowser ein bisschen gesehen, bevor ich deine Antwort gesehen habe. Ich habe auch versucht, mit LockModes und sogar __MIDL___MIDL_itf_autosvcs_0469_0002 ohne Erfolg vorangestellt. Der Code entspricht so wie er ist. Wenn ich es vorstelle, wird es nicht kompilieren. –

Verwandte Themen