Why are Visual Type 6.0 not displaying TypeLib enums presented as enumerations?

I have a VB6 project that references COMSVCSLib, and one of the methods calls COMSVCSLib SharedPropertyGroupManager.CreatePropertyGroup calls, passing LockMethod and Process as parameters.

Purified 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, at first I thought that LockMethod and Process are variables or constants defined elsewhere in the project.

After a little research in the Object Browser, I found that both of them were exposed as constants in COMSVCSLib.

Object browser

However, looking at their definition in the OLE / COM Object Viewer, they appear to be defined as enumeration values:

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

Why IDL / TypeLib instances from COMSVCSLib are not displayed as enumerations on Visual Basic 6.0?

+6
enums constants vb6 typelib
source share
2 answers

Disclaimer I'm not an IDL specialist (an interface definition language that is used to define COM types) or a Microsoft IDL compiler (MIDL), but I came to the conclusions below after playing with the type library for scrrun.dll, which has a similar enumeration problem. Some of this information was obtained from a quick review of this DevX article on IDL and VB6: IDL for VB Tutorial

VB6 expects the actual enumeration to have a name, not just the enumeration that typedef 'd for the name. The name __MIDL___MIDL_itf_autosvcs_0469_0002 is a placeholder, since the original typelib did not specify the enumeration name in the same typedef where the enumeration constants are defined.

When you browse the type library in the OLE Viewer, enum probably looks like this:

 typedef [public] __MIDL___MIDL_itf_autosvcs_0469_0002 LockModes; typedef enum { LockSetGet = 0, LockMethod = 1 } __MIDL___MIDL_itf_autosvcs_0469_0002; 

The first typedef creates the public name LockModes as an alias for the automatically generated name MIDL___MIDL_itf_autosvcs_0469_0002 , which was assigned to enum . When the source libary type was compiled, the midl compiler generated a long __MIDL name for the source enum and automatically created an alias of typedef pointing to it.

The source IDL probably defined the enumeration as follows:

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

When the midl compiler processes the enum definition written in this way, it automatically generates a name for enum (since it is absent, it should appear after the enum keyword). This is the __MIDL name that you see when viewing the type library in the OLE Viewer. The midl compiler also automatically generates a second typedef , which midl typedef name for the automatically generated enum name.

The problem is that VB6 cannot understand the enum created in this way. He expects everything to be in one typedef (i.e. you will give the name enum , and also name typedef ):

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

IDL treats typedef as C or C ++ does: you do not need to specify enum as a name because typedef already has a name, but you can specify an enumeration name if you select. In other words, typedef and enum are actually two separate objects. VB6 discovers that typedef and enum are two different but vaguely related things, so in your case it sees a typedef called __MIDL___MIDL_itf_autosvcs_0469_0002 , and it sees that it is an alias of an unnamed enum, and also sees a typedef for LockModes , which is a public alias for another alias typedef .

Since the first typedef is public, you will see an entry for LockModes in the object browser, and since it is an alias for an enumeration, you will see the enumeration constants in the object browser. However, the actual enumeration does not have a name (so it gets the funky auto-generated name assigned to it in the browser), and VB6 cannot use the enumeration because the auto-generated name in VB6 is illegal (double underlined names are automatically hidden in VB6).

To demonstrate this last point, if you type it in your VB6 code, Intellisense will work and it will compile, but obviously this is not very ideal:

 MsgBox COMSVCSLib.[__MIDL___MIDL_itf_autosvcs_0469_0002].LockMethod 

The reason this code works is because you can put names that usually cause syntax errors (for example, names starting with an underscore) in brackets to allow VB6 to accept a normally illegal name. In addition, the prefix of constants with an auto-generated name works with Intellisense because it is the actual name that VB6 associates with enum (remember that another typedef is just an alias for this β€œreal”, generated name, and VB6 apparently cannot put all the parts together so that both names refer to the same enum ).

Instead of typing the ridiculous name as described above, you can also access the enum constants, prefixing them with the library name, for example, COMSVCSLib.LockMethod should work. It’s less clear to me why this really works, and I'm not sure what will happen if two different enum define constants with the same name.

Finally, you can fix this problem differently by using the IDL from the OLE Viewer to create a custom IDL file in which you replace the existing enum typedefs with one typedef for each enum , which simply gives both enum and typedef the same name (i.e. e. typedef enum LockModes { ... } LockModes; ), but since the OLE Viewer does not necessarily generate a valid IDL, you probably have to tweak it even more to make it actually compile. If you can make it work, you can reference to your own .tlb from your VB6 project (instead of the COMSVCSLib library COMSVCSLib ), and enum will work as you would expect from them.

If you want to go this route, you need two more tools that must be installed on your development machine (but you may need to find them):

  • midl.exe : this tool can generate a typelib file (* .tlb) from a .idl file. Thus, you can copy the IDL from the OLE Viewer to Notepad, change the enumeration definitions as described above, save it as an .idl file .idl and transfer it to midl.exe to create a new typelib:

    midl my-custom-typelib.idl

  • regtlib.exe : this tool can register the .tlb file that is required if you want to add it as a link to your VB6 project:

    regtlib.exe my-custom-typelib.tlb

However, creating a custom typelib for this is probably too large, and as already mentioned, it can be difficult to get a compiled IDL file based on the output from the OLE Viewer, since it displays the inverse IDL construct for the type library, rather than the original IDL.

+10
source share

It is displayed as an enumeration. Select LockModes in the list of classes and take a look at the bottom section of the information. You will see that this listing. Or you can enter LockModes. into your code and you will get two options.

In the object viewer, each item in the enumeration is identified as a constant value, but it is not an autonomous constant. Autonomous constants are listed separately when you select the <globals> element in the class list.

+1
source share

All Articles