I have a VB6 project that references COMSVCSLib and one of the methods makes calls to COMSVCSLib’s SharedPropertyGroupManager.CreatePropertyGroup passing LockMethod and Process as parameters.
Cleaned up 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
Having not worked with VB6 for several years now, at first I thought LockMethod and Process were variables or constants defined somewhere else within the project.
After a little research on the Object Browser I found out that they were both being exposed as constants in COMSVCSLib.

But looking at their definition in OLE/COM Object Viewer, they seem to be defined as values of an enumeration:
typedef enum {
LockSetGet = 0,
LockMethod = 1
} __MIDL___MIDL_itf_autosvcs_0469_0002;
Why aren’t IDL/TypeLib enums from COMSVCSLib being exposed as enums to Visual Basic 6.0?
Disclaimer: I’m not an expert on IDL (Interface Definition Language, which is the language used to define COM types) or the Microsoft IDL compiler (MIDL), but I came to the conclusions below after playing around with the type library for scrrun.dll, which has a similar problem with enum’s. Some of this information was gleaned from a quick look at this DevX article on IDL and VB6: IDL for VB Tutorial
VB6 expects the actual enum to have a name, not just a enum that is
typedef‘d to a name. The__MIDL___MIDL_itf_autosvcs_0469_0002name is a placeholder, since the original typelib didn’t define the enum name in the sametypedefwhere the enum constants are defined.When you view the type library in OLE Viewer, the
enumprobably looks like this:The first
typedefcreates the public nameLockModesas an alias for the auto-generatedMIDL___MIDL_itf_autosvcs_0469_0002name that was given to theenum. When the original type libary was compiled, themidlcompiler generated the long__MIDLname for the originalenumand automatically created atypedefalias pointing back to it.The original IDL probably defined the enum like this:
When the
midlcompiler processes anenumdefinition written this way, it auto-generates a name for theenum(since it is missing – it should appear after theenumkeyword). This is what the__MIDLname is that you see when you view the type library in OLE Viewer. Themidlcompiler also automatically generates a secondtypedefthat aliases thetypedefname to the auto-generatedenumname.The problem is that VB6 can’t understand enum’s that are created this way. It expects everything to be in a single
typedef(i.e. you give theenuma name, as well as naming thetypedef):IDL treats
typedef‘s the same way that C or C++ does: you don’t have to give the enum itself a name, because thetypedefalready has a name, but you can give the enum a name if you choose. In other words, thetypedefand theenumare actually two separate entities. VB6 happens to recognize thetypedefand theenumas being two distinct, but vaguely-related things, so in your case it sees atypedefnamed__MIDL___MIDL_itf_autosvcs_0469_0002, and it sees that this is an alias to an unnamed enum, and it also sees atypedefforLockModes, which is a public alias for the othertypedef.Since the first
typedefis public, you will see an entry forLockModesin the Object Browser, and because it is an alias for an enum, you will see the enum constants in the Object Browser as well. However, the actual enum itself does not have a name (so it gets the funky auto-generated name assigned to it in the browser), and VB6 can’t use the enum because the auto-generated name happens to be illegal in VB6 (names with double-underscores are automatically hidden in VB6).To demonstrate that last point, if you type this in your VB6 code, Intellisense will work and it will compile, but obviously, it’s not very ideal:
The reason this code works is because you can put names that normally cause syntax errors (such as names that start with underscores) in brackets to allow VB6 to accept the normally-illegal name. In addition, prefixing the constants with the auto-generated name works with Intellisense because it is the actual name that VB6 associates with the
enum(remember the othertypedefis just an alias back to this “real”, but auto-generated name, and VB6 apparently can’t put all the pieces together to realize both names refer to the sameenum).Rather than typing out the ridiculously-long name like above, you can also access
enumconstants by prefixing them with the library name, for example,COMSVCSLib.LockMethodshould work. It’s less clear to me why this actually works, and I’m not sure what would happen if two differentenum‘s define constants with the same name.Lastly, you could fix this problem a different way by using the IDL from the OLE Viewer to create a custom IDL file, in which you replace the existing
enumtypedefs with a singletypedeffor eachenumthat simply gives both theenumand thetypedefthe same name (i.e.typedef enum LockModes { ... } LockModes;), but since the OLE Viewer doesn’t necessarily generate valid IDL, you would probably have to tweak it even more to get it to actually compile. If you can get this to work, then you can reference your custom.tlbfrom your VB6 project (instead of theCOMSVCSLiblibrary), and theenum‘s will work like you would expect them to.If you want to go that route, there are two other tools you need, which should already been installed on your development machine (but you may need to search for them):
midl.exe: This tool can generate a typelib file (*.tlb) from a.idlfile. So you could copy the IDL from the OLE Viewer into Notepad, modify the enum definitions as described above, save it as a.idlfile, and pass it tomidl.exeto make a new typelib:midl my-custom-typelib.idlregtlib.exe: This tool can register a .tlb file, which is required if you want to be able to add it as a reference to your VB6 project:regtlib.exe my-custom-typelib.tlbHowever, creating a custom typelib for this is probably overkill, and as already mentioned, it might be hard to get a compilable IDL file based off the output from the OLE Viewer, since it displays reverse-engineered IDL for the type library, not the original IDL.