Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Variable verwendet einen in Visual Basic nicht unterstützten Automatisierungstyp (Fehler 458)

445 views
Skip to first unread message

Ulrich Korndoerfer

unread,
Sep 29, 2001, 4:38:12 PM9/29/01
to
Hallo NG,

es ist zum Verzweifeln.

Beim Erstellen eines User-Controls (native Code, VB6 SP5) wirft der
Compiler obige Fehlermeldung mit folgender Erläuterung:

"Nicht jede Variable, die in einer Klassenbibliothek oder einer
Objektbibliothek enthalten ist, kann von jeder Programmiersprache
verwendet werden. Für diesen Fehler gibt es die folgende Ursache und
Lösung:

Sie haben versucht, eine Variable zu verwenden, die in einer
Klassenbibliothek oder Objektbibliothek mit einem Datentyp definiert
worden ist, der von Visual Basic nicht unterstützt wird.

Sie können in einem Visual Basic-Programm keine Variable verwenden,
deren Typ Visual Basic nicht kennt."

Leider ist er nicht so nett, mir mitzuteilen wo oder um welche Variable
oder welchen Typ es sich handelt.

Eingebunden sind:

Verweise:

Microsoft Access 9.0 Object Library
Microsoft DAO 3.60 Object Library
Microsoft Data Source Interfaces (msdatsrc.tlb)
Microsoft ActiveX Data Objects 2.6 Library

Komponenten:

keine

Um es gleich vorwegzunehmen: alles hat bis vor kurzem noch funktioniert
(mit obigen Verweisen und deren Gebrauch). Nach ein paar Änderungen -
peng.

Habe alle Deklarationen durchgeflöht - keine war auffällig im Sinne der
Fehlermeldung (wenn ich die richtig verstanden habe). Einzig merkwürdig
ist, das z.B. bei

Dim rs as adodb.Recordset

das adodb klein bleibt. Das war vorher aber auch schon so.

Wer kann mir einen Hinweis geben, wo ich hinfassen muß, um das in den
Griff zu bekommen.

Ulrich

Peter Fleischer

unread,
Oct 1, 2001, 2:37:44 AM10/1/01
to
Ulrich,
wenn du zwei Objektbibliotheken mit sich überschneidenden Definitionen
nutzt, dann musst du unbedingt in deinen Deklarationen den richtigen
Bibliotheksnamen voransetzen. Wenn du das nicht machst, kann es
passieren, dass die falsche Definition genutzt wird, da VB in der
Reihenfolge der Verweise auflöst.

Beispiel:

Microsoft DAO 3.60 Object Library

Microsoft ActiveX Data Objects 2.6 Library

...
Dim rs as Recordset
...
rs.Open "Tabelle", cnn

rs wird von VB als DAO-Recordset interpretiert, die Open-Methode mit der
ADO-Connection funktioniert so aber nicht.

Peter

"Ulrich Korndoerfer" <ulrich.ko...@t-online.de> schrieb im
Newsbeitrag news:3BB63134...@t-online.de...

Ulrich Korndoerfer

unread,
Oct 1, 2001, 9:53:17 AM10/1/01
to
Hallo Peter,

Peter Fleischer schrieb:



> Ulrich,
> wenn du zwei Objektbibliotheken mit sich überschneidenden Definitionen
> nutzt, dann musst du unbedingt in deinen Deklarationen den richtigen
> Bibliotheksnamen voransetzen. Wenn du das nicht machst, kann es
> passieren, dass die falsche Definition genutzt wird, da VB in der
> Reihenfolge der Verweise auflöst.

Ja. ist klar. Habe im Code nur qualifizierte Namen verwendet (also
DAO.Recordset, ADODB.Recordset etc.). Trotzdem gibts Probleme.

Neuester Stand:

Habe jetzt einige Verweise und Code-Teile aus dem Projekt entfernt.
Enthalten sind jetzt noch folgende Verweise (und Code, der Objekte aus
den verwiesenen Bibliotheken benutzt):

Microsoft Data Source Interfaces (msdatsrc.tlb)
Microsoft ActiveX Data Objects 2.6 Library

Leider ohne Erfolg.

Ulrich

Lukas Pietsch

unread,
Oct 1, 2001, 11:51:17 AM10/1/01
to
Hallo Ulrich,

>
> Sie können in einem Visual Basic-Programm keine Variable verwenden,
> deren Typ Visual Basic nicht kennt."
>
> Leider ist er nicht so nett, mir mitzuteilen wo oder um welche Variable
> oder welchen Typ es sich handelt.

so eine Meldung habe ich auch gerade bei einem Projekt bekommen. In meinem
Fall hat mir aber der Objekt-Browser angezeigt, welche Variable das war.
Hast du mal versucht, im Objekt-Browser alle Mitglieder der verwendeten
Bibliotheken abzuklappern?

Gruß,

Lukas


Ulrich Korndoerfer

unread,
Oct 1, 2001, 11:59:29 AM10/1/01
to
Hallo NG,

habs gefunden.

In einem Klassenmodul (das OCX enthält UserControls, einige Klassen und
ein Standardmodul) war folgender Code:

Public Sub SetActionFind(ByVal Criterium As String, _
Optional ByVal SkipRows As Long = 0, _
Optional ByVal SearchForward As Boolean = True,
_
Optional ByVal StartBookmark As Variant =
Empty)

SetAction ukadcActionFind, Criterium, SkipRows, SearchForward,
StartBookmark

End Sub

Der Defaultteil für StartBookmark ist zwar überflüssig (da eh zu Empty
initalisiert wird), aber ich bevorzuge diese Schreibweise aus Gründen
der besseren Lesbarkeit.

Wenn nun in:

Public Sub SetActionFind(ByVal Criterium As String, _
Optional ByVal SkipRows As Long = 0, _
Optional ByVal SearchForward As Boolean = True,
_
Optional ByVal StartBookmark As Variant)

abgeändert, wird ohne Fehlermeldung kompiliert.

Dies läßt mich nun doch etwas ratlos zurück. Wie passt das bitte zur
Fehlermeldung? Wieso ergibt das überhaupt einen Fehler? Wieso wird die
fehlerhafte Stelle nicht angezeigt? Mit anderen Worten: was soll der
Quatsch?

Ulrich

Ulrich Korndoerfer

unread,
Oct 1, 2001, 12:11:00 PM10/1/01
to
Hallo Lukas,

es geht hier bei mir auschließlich um MS-Bibliotheken, die für die
Automatisierung gedacht sind. Die sollten also auch nur
automatisierungsfeste Typen verwenden. Außerdem habe ich bis jetzt nur
eine Handvoll Typen aus diesen Bibliotheken verwendet, und zwar alles
Typen, die ich schon immer verwendet habe (wie z.B. ein Recordset-Objekt
und ähnliches). Sollte also nicht in Frage kommen. Hab die Ursache eh
schon gefunden, (siehe weiter unten im Thread).

Was mich interessieren würde: Du verwendest anscheinend eine Bibliothek,
welche Nicht-Automatisierungstypen verwendet. Wie wird denn ein solcher
Typ im Objektbrowser angezeigt? Ich dachte, der benutzt COM-"Reflection"
(Typelibs). Und ein COM-Typ sollte automatisierungsfest sein. Wenn er es
also nicht ist, wie kann ihn dann der Objektbrowser anzeigen?

Ulrich

Steffen Ramlow

unread,
Oct 1, 2001, 5:19:49 PM10/1/01
to
"Ulrich Korndoerfer" <ulrich.ko...@t-online.de> wrote in message

> Dies läßt mich nun doch etwas ratlos zurück. Wie passt das bitte zur
> Fehlermeldung? Wieso ergibt das überhaupt einen Fehler? Wieso wird die
> fehlerhafte Stelle nicht angezeigt? Mit anderen Worten: was soll der
> Quatsch?

das keyword "Empty" hat nix mit COM zu tun, deshalb paßt's auch nich in die
von vb erzeugte IDL, weiß der geier, was vb da beim kompilieren tut
warum nix vernünftige meldung: auch VB hat reichlich buckz, nich nur die von
dir verzapfte software :-)

Ulrich Korndoerfer

unread,
Oct 1, 2001, 7:31:17 PM10/1/01
to
Hallo Steffen,


Steffen Ramlow schrieb:

[...]


> das keyword "Empty" hat nix mit COM zu tun, deshalb paßt's auch nich in die
> von vb erzeugte IDL, weiß der geier, was vb da beim kompilieren tut

Lt. Doku ist Empty ein Schlüsselwort, welches einen Wert vom Typ
Variant, Untertyp Empty repräsentiert.

Hm, in meiner Unschuld habe ich angenommen, daß, da ein Variant ja eine
Struktur ist, die in COM des öfteren zu finden ist, VB auch nur in COM
definierte Untertypen verwendet.

Der Code:

Public Sub testA()
Dim v As Variant
v = Empty
If VarType(v) = vbEmpty Then MsgBox "Empty"
End Sub

wird anstandslos übersetzt,

Public Sub testB(Optional ByVAl v as Variant = Empty)
End Sub

dagegen nicht.

Nach Deiner Erklärung müßte das daran liegen, daß in testA die
Verwendung von Empty nicht die Schnittstelle beeinflußt. Hm, scheint
Sinn zu machen. Bedeutet dann außerdem, daß der Aufrufer von testB den
Wert vom Typ Empty bereitstellen müßte. Und da der Aufrufer außerhalb
der Bibliothek sein kann, müßte diesem der Variantuntertyp Empty bekannt
sein, welcher aber anscheinend nicht in COM definiert ist.

Da gibt es aber noch ein kleines Problem:

Dim vvv as Variant

Public Sub testC(Optional ByVal v As Variant)
Dim vv As Variant
MsgBox "VarType(v): " & CStr(VarType(v)) & vbCrLf & _
"VarType(vv): " & CStr(VarType(vv)) & vbCrLf & _
"VarType(vvv): " & CStr(VarType(vvv))
End Sub


wird ebenfalls anstandslos übersetzt und ergibt, wenn von außerhalb und
innerhalb der Bibliothek aufgerufen, jeweils für v den Subtype vbError
(10), für vv und vvv den Subtype vbEmpty (0). Der gleiche Code in einer
Standardexe mit Aufruf in derselben liefert das gleiche Ergebnis. Das
heißt, innerhalb einer Prozedur muß bei dem Versuch, auszuwerten, ob
eine Variant initialisiert ist, zwischen einem lokalen oder globalen
Variant und einem übergebenen Variant unterschieden werden.

Andererseits ist in einer Standardexe

Dim vvv as Variant

Public Sub testD(Optional ByVal v As Variant = Empty)
Dim vv As Variant
MsgBox "VarType(v): " & CStr(VarType(v)) & vbCrLf & _
"VarType(vv): " & CStr(VarType(vv)) & vbCrLf & _
"VarType(vvv): " & CStr(VarType(vvv))
End Sub

problemlos möglich und ergibt dreimal den Subtype Empty.

Oh Wirrwarr.

> warum nix vernünftige meldung: auch VB hat reichlich buckz, nich nur die von
> dir verzapfte software :-)

Meine Software hat nur Features :-)


Ulrich

Ulrich Korndoerfer

unread,
Oct 1, 2001, 10:59:05 PM10/1/01
to
Hallo Steffen,

habe noch ein bißchen gestöbert.

Aus

Plattform-SDK
COM and ActiveX Object Services
Automation
Data Types, Structures, and Enumerations
IDispatch Data Types and Structures
VARIANT and VARIANTARG:

[...]
typedef struct tagVARIANT {
VARTYPE vt;
unsigned short wReserved1;
unsigned short wReserved2;
unsigned short wReserved3;
union {
unsigned char bVal; // VT_UI1.
short iVal;
[...]

The vt value governs the interpretation of the union as follows:

Value

VT_EMPTY

Description

No value was specified. If an optional argument to an Automation method
is left blank, do not pass a VARIANT of type VT_EMPTY. Instead, pass a
VARIANT of type VT_ERROR with a value of DISP_E_PARAMNOTFOUND
[...]

Scheint so zu sein, daß VT_EMPTY durchaus COM-bekannt ist, aber es bei
einer optionalen Parameterübergabe nicht verwendet werden darf. Der
Callee muß sich darauf verlassen können, daß er im Falle eines fehlenden
Argumentes einen Variant vom Typ vbError überreicht bekommt. Das könnte
der Grund sein, warum VB eine explizite Belegung mit Empty nicht zuläßt.


Ulrich

Ulrich Korndoerfer

unread,
Oct 1, 2001, 11:20:25 PM10/1/01
to
Hallo nochmal,

> Der
> Callee muß sich darauf verlassen können, daß er im Falle eines fehlenden
> Argumentes einen Variant vom Typ vbError überreicht bekommt. Das könnte
> der Grund sein, warum VB eine explizite Belegung mit Empty nicht zuläßt.


Quark.

Der Caller stünde vor einem Problem, wenn in der Methodendeklaration via
Defaultwertzuweisung von ihm verlangt werden würde, ein Empty-Variant im
Falle des Fehlens zu übergeben. Das ergäbe einen Widerspruch zu der
Regel im vorigen Post.

Ob das nun der wirkliche Grund ist, warum VB sich einerseits strikt an
COM hält, andererseits (siehe testD weiter oben), solange alles in der
Familie bleibt, Fünfe auch mal grade sein läßt?

Ulrich

Steffen Ramlow

unread,
Oct 2, 2001, 4:46:18 AM10/2/01
to
ich würde mal sagen: beim kompilieren wird angenommen: vbEmpty = VT_EMPTY <>
Empty

--
Steffen Ramlow: s.ra...@gmx.de
Enterprise Development: http://www.dev-purgatory.org/

"Ulrich Korndoerfer" <ulrich.ko...@t-online.de> wrote in message

news:3BB93279...@t-online.de...

Ulrich Korndoerfer

unread,
Oct 2, 2001, 10:36:24 AM10/2/01
to
Hallo Steffen,


Steffen Ramlow schrieb:
>

> ich würde mal sagen: beim kompilieren wird angenommen: vbEmpty = VT_EMPTY <>
> Empty

Aber Empty = VARIANT mit VARTYPE vt = VT_EMPTY.

Ulrich

Steffen Ramlow

unread,
Oct 2, 2001, 11:55:42 AM10/2/01
to


"Ulrich Korndoerfer" <ulrich.ko...@t-online.de> wrote in message

news:3BB9D0E8...@t-online.de...

> Aber Empty = VARIANT

wo steht das denn?


Ulrich Korndoerfer

unread,
Oct 2, 2001, 1:52:54 PM10/2/01
to
Hallo Steffen,


Steffen Ramlow schrieb:

> > Aber Empty = VARIANT
>
> wo steht das denn?

Doku:


A)

Das Schlüsselwort Empty wird als Variant-Untertyp verwendet und zeigt
einen nicht initialisierten Variablenwert an


B)

Der Wert Empty

Manchmal müssen Sie bestimmen, ob einer Variablen überhaupt ein Wert
zugewiesen wurde. Eine Variant-Variable hat den Wert Empty, solange ihr
noch kein Wert zugewiesen wurde. Der Wert Empty ist ein besonderer Wert
und unterscheidet sich von 0, einer Nullzeichenfolge ("") und dem Wert
Null.
[...]
Sie können eine Variant-Variable auf den Wert Empty zurücksetzen, indem
Sie ihr das Schlüsselwort Empty zuweisen.


C)

Empty

Zeigt an, daß einer Variablen vom Typ Variant kein Anfangswert
zugewiesen worden ist. Eine Variable vom Typ Empty wird durch eine Null
(0) in einem numerischen Kontext oder durch eine Null-Zeichenfolge ("")
in einem Zeichenfolgenkontext dargestellt.


und:

D)

If VarType(Empty) = vbEmpty Then MsgBox "Empty"

lässt die Messagebox aufpoppen. Da ein Wert vom VarType vbEmpty nur ein
Variant sein kann, muß Empty ein Variant vom VarType vbEmpty sein.

Ulrich

Steffen Ramlow

unread,
Oct 2, 2001, 2:03:33 PM10/2/01
to


"Ulrich Korndoerfer" <ulrich.ko...@t-online.de> wrote in message

news:3BB9FEF6...@t-online.de...

> muß Empty ein Variant vom VarType vbEmpty sein.

ju, oke
aber was sollz, is halt so

Ulrich Korndoerfer

unread,
Oct 2, 2001, 2:37:08 PM10/2/01
to
Hallo Steffen,


Steffen Ramlow schrieb:

> > muß Empty ein Variant vom VarType vbEmpty sein.


>
> ju, oke
> aber was sollz, is halt so


Wo Du Recht hast, hast Du recht :-)

Ulrich

Harald M. Genauck

unread,
Oct 12, 2001, 12:21:45 AM10/12/01
to
Hallo Steffen,

> ich würde mal sagen: beim kompilieren wird angenommen: vbEmpty = VT_EMPTY
<>
> Empty

Logo. Der Wert Empty ist wirklich etwas anderes als die VarType-Konstante
vbEmpty (alias VT_EMPTY)...


Viele Grüße

Harald M. Genauck

ABOUT Visual Basic - das Webmagazin
http://www.aboutvb.de

Harald M. Genauck

unread,
Oct 12, 2001, 12:21:44 AM10/12/01
to
Hallo Ulrich,

>> No value was specified. If an optional argument to an Automation method
>> is left blank, do not pass a VARIANT of type VT_EMPTY. Instead, pass a
>> VARIANT of type VT_ERROR with a value of DISP_E_PARAMNOTFOUND
>> [...]

> Scheint so zu sein, daß VT_EMPTY durchaus COM-bekannt ist, aber es bei
> einer optionalen Parameterübergabe nicht verwendet werden darf. Der
> Callee muß sich darauf verlassen können, daß er im Falle eines fehlenden
> Argumentes einen Variant vom Typ vbError überreicht bekommt. Das könnte
> der Grund sein, warum VB eine explizite Belegung mit Empty nicht zuläßt.

Daher auch die IsMissing-Funktion - sie funktioniert ja auch nur mit
optionalen Variant-Parametern.

Außerdem:

Private Sub Command1_Click()
XY
End Sub

Private Sub XY(Optional abc As Variant)
Debug.Print VarType(abc)
End Sub

->> ergibt 10, als vbError!

Da aber auch optionale Parameter bei Methoden von VB-Objekten, etwa bei der
Add-Methode der Collection als "Nichts" das vbError erwarten, funktioniert
so auch das Durchreichen von Nichts ohne Probleme und Gemeutere:

Sub MyAdd(Item As Irgendwas, Optional Key As Variant)
IrgendeineCollection.Add Item, Key
End Sub

Ulrich Korndoerfer

unread,
Oct 12, 2001, 9:58:42 AM10/12/01
to
Hallo Harald!

Wo bist Du denn in den letzten Woche abgeblieben? Urlaub? Hab Dich schon
vermisst und war kurz vor der Vermisstenanzeige ;-).

Zum Thema:


> Da aber auch optionale Parameter bei Methoden von VB-Objekten, etwa bei der
> Add-Methode der Collection als "Nichts" das vbError erwarten, funktioniert
> so auch das Durchreichen von Nichts ohne Probleme und Gemeutere:
>
> Sub MyAdd(Item As Irgendwas, Optional Key As Variant)
> IrgendeineCollection.Add Item, Key
> End Sub

Ist das generell so, also z.B. auch bei ADO-Objekten?

Beispiel:


Public Sub SetActionFind(ByVal Criterium As String, _
Optional ByVal SkipRows As Long = 0, _
Optional ByVal SearchForward As Boolean = True,
_
Optional ByVal StartBookmark As Variant)

Dim RS as ADODB.RecordSet
Dim Direction as Long

If SearchForward Then Direction = adSearchForward Else Direction =
adSearchBackWard

Rs.Find Criterium, SkipRows, Direction, StartBookmark

End Sub

StartBookmark setzt eine Position im Recordset, ab der die Suche
beginnen soll. Der Parameter ist in der Find Methode als optionaler
Variant deklariert.

Bisher habe ich das so gelöst, daß ich auswerte, ob ein Wert für
Startbookmark übergeben wurde und dann entsprechend zwei verschiedene
Aufrufe von Find durchführe, einen mit und einen ohne diesen Parameter.
Deinen Ausführungen gemäß könnt ich mir das sparen.

Ulrich


Harald M. Genauck

unread,
Oct 12, 2001, 12:07:47 PM10/12/01
to
Hallo Ulrich,

> Wo bist Du denn in den letzten Woche abgeblieben? Urlaub? Hab Dich schon
> vermisst und war kurz vor der Vermisstenanzeige ;-).

Habe einen Murphy-Kurs gemacht... ;-)

> > Da aber auch optionale Parameter bei Methoden von VB-Objekten, etwa bei
der
> > Add-Methode der Collection als "Nichts" das vbError erwarten,
funktioniert
> > so auch das Durchreichen von Nichts ohne Probleme und Gemeutere:
> >
> > Sub MyAdd(Item As Irgendwas, Optional Key As Variant)
> > IrgendeineCollection.Add Item, Key
> > End Sub

> Ist das generell so, also z.B. auch bei ADO-Objekten?

Wenn diese im Sinne der bisherigen Ausführungen "ordentlich" programmiert
bzw. deren TLBs ok sind, dann dürfte das auch bei ADO funktionieren.
Garantieren kann ich es natürlich nicht.

> Bisher habe ich das so gelöst, daß ich auswerte, ob ein Wert für
> Startbookmark übergeben wurde und dann entsprechend zwei verschiedene
> Aufrufe von Find durchführe, einen mit und einen ohne diesen Parameter.
> Deinen Ausführungen gemäß könnt ich mir das sparen.

Das war früher auch meine Taktik, bis ich gemerkt habe, dass es auch
"automatisch" geht. Allerdings mit einem Vorbehalt: Es geht nur bei
optionalen Variant-Parametern! Optionale Parameter anderer Datentypen
übermitteln jeweils ihren Standard-Initialisierungswert, wenn sie
weggelassen werden und nicht eine Vorbelegung angegeben ist.

0 new messages