Access
 sql >> Datenbank >  >> RDS >> Access

DefType-Anweisungen in VBA:Die dunkle Seite der Abwärtskompatibilität

Nur weil Sie etwas tun können, heißt das nicht, dass Sie es tun sollten.

Ich glaube fest an die Heiligkeit der Abwärtskompatibilität. Aber es kommt mit einer dunklen Seite. Manchmal geraten die alten Vorgehensweisen in Ungnade. Ihr Gebrauch wird so geheimnisvoll, dass wir dazu neigen zu vergessen, dass sie überhaupt existieren.

So verhält es sich mit DefType-Anweisungen.

Was Sie nicht wissen, kann Sie verletzen

Vor einigen Monaten habe ich einen Artikel über das Klassenmodul Registry Operations von Romke Soldaat geschrieben.

Ich habe die Änderungen veröffentlicht, die ich an Romkes API-Deklarationen vorgenommen habe, damit der Code unter 64-Bit-VBA ausgeführt werden kann. Jeder API-Aufruf wurde in #If VBA7 eingeschlossen bedingte Kompilierungs-Tags und aktualisiert mit dem PtrSafe Schlüsselwort.

Es gab nur ein Problem.

Ich habe vergessen, eine wichtige Änderung einzufügen, die ich an einer der Deklarationen auf Modulebene in Romkes Code vorgenommen hatte. Ohne diese Änderung würde der modifizierte Code von Romke nicht unter 64-Bit-VBA kompiliert werden. Der Kompilierfehler ist in der folgenden Zeile aufgetreten:

Die Fehlermeldung lautete „Nichtübereinstimmung des ByRef-Argumenttyps " und die hervorgehobene Variable war hCurKey .

Hier ist die beleidigende Codezeile aus Romkes ursprünglichem Klassenmodul:

Private hCurKey

Um den Kompilierfehler zu beheben, kann die obige Codezeile wie folgt geändert werden:

Private hCurKey As Variant

Aber warte, sagst du, tun diese beiden Codezeilen nicht dasselbe?!?! Jeder weiß, dass, wenn Sie den Typ einer Variablen nicht in VBA deklarieren, sie implizit als Variant deklariert wird. ...  Oder doch?

Explizit ist besser als implizit

Also, was geht hier wirklich vor?

Das Problem ist, dass die erste Codezeile oben – Private hCurKey –definierte die hCurKey-Variable als Long Datentyp.

Wie konnte das sein?

Das lag an dieser seltsamen Zeile oben in Romkes Klassenmodul:

DefLng H-I, L, N

Was macht diese Linie? Das heißt, jede deklarierte Variable im aktuellen Modul ohne explizit deklarierten Typ, deren Variablenname mit H beginnt , I , L , oder N , wird vom Compiler als Long behandelt Datentyp.

Also die Zeile Private hCurKey tat implizit Deklarieren Sie einen Typ für die hCurKey-Variable, aber die implizite Deklaration war ein Long-Datentyp anstelle eines Variant.

Warum funktioniert Variant Kompilieren, aber lang Nicht?

Warum der Code kompiliert wird, wenn hCurKey ein Variant ist, aber fehlschlägt, wenn es ein Long ist, das ist eine Frage des 32-Bit-zu-64-Bit-Konvertierungsprozesses.

Um die Ursache des Problems zu finden, müssen wir den migrierten Code für die RegCreateKeyEx-API-Deklaration untersuchen:

#If VBA7 Then
    Private Declare PtrSafe Function RegCreateKeyEx _
      Lib "advapi32.dll" Alias "RegCreateKeyExA" ( _
          ByVal hKey As LongPtr, ByVal lpSubKey As String, _
          ByVal Reserved As Long, ByVal lpClass As String, _
          ByVal dwOptions As Long, ByVal samDesired As Long, _
          lpSecurityAttributes As SECURITY_ATTRIBUTES, _
          phkResult As LongPtr, lpdwDisposition As Long) As Long
#Else
    Private Declare Function RegCreateKeyEx _
      Lib "advapi32.dll" Alias "RegCreateKeyExA" ( _
          ByVal hKey As Long, ByVal lpSubKey As String, _
          ByVal Reserved As Long, ByVal lpClass As String, _
          ByVal dwOptions As Long, ByVal samDesired As Long, _
          lpSecurityAttributes As SECURITY_ATTRIBUTES, _
          phkResult As Long, lpdwDisposition As Long) As Long
#End If

Wenn wir RegCreateKeyEx aufrufen aus dem Code übergeben wir den hCurKey Variable als vorletztes Argument in der Funktion. Mit anderen Worten, es wird als phkResult übergeben Streit. Beachten Sie, dass in der Version vor VBA7 (Access 2007 und früher) phkResult als Long deklariert, aber in der VBA7-Version als LongPtr deklariert .

Das liegt daran, dass phkResult erhält ein Handle zum erstellten oder geöffneten Registrierungsschlüssel. Wann immer Sie das Wort „Handle“ in Verbindung mit einem API-Aufruf sehen, können Sie es in Ihrem Kopf sicher in „Speicheradresse“ übersetzen. Deshalb wird das Argument als LongPtr neu definiert im VBA7-Code:bei der Ausführung in einer 32-Bit-Umgebung ein LongPtr wird als 32-Bit Long behandelt Ganzzahl, aber in einer 64-Bit-Umgebung ein LongPtr wird als 64-Bit LongLong behandelt Ganzzahl.

hCurKey deklarieren as Variant ist eine Art Abkürzung. Die folgende Anpassung würde auch funktionieren (und schneller ablaufen, obwohl die Geschwindigkeitserhöhung für den Benutzer wahrscheinlich nicht wahrnehmbar ist, es sei denn, sie wird viele Male innerhalb einer Schleife aufgerufen):

#If VBA7 Then
    Private hCurKey As LongPtr
#Else
    Private hCurKey As Long
#End If

Wie ich bereits sagte, vermittelt der obige Ansatz die Absicht des Entwicklers deutlicher, ist leistungsfähiger und führt zu mehr Fehlern bei der Kompilierung als der Private hCurKey As Variant Alternative.

Aber ich bin ja bekanntlich faul und Private hCurKey As Variant ist fast genauso gut mit viel weniger Tippen.

Nutzen Sie Ihr Wissen für das Gute

Erinnern Sie sich, was ich am Anfang dieses Artikels gesagt habe?

Nur weil du etwas tun kannst, heißt das nicht, dass du es tun solltest.

Ich habe diesen Artikel aus zwei Gründen geschrieben:

  1. Um Sie ausdrücklich dazu zu ermutigen Deklarieren Sie Variant-Variablen As Variant
  2. Um das Bewusstsein für einen geheimnisvollen Aspekt von VBA zu schärfen, der Sie ins Stolpern bringen könnte, wenn Sie den Code einer anderen Person warten (oder kopieren und einfügen)

ICH HABE NICHT Schreiben Sie diesen Artikel, um Sie dazu zu inspirieren, DefType-Anweisungen in Ihrem eigenen Code zu schreiben. TU DAS NICHT!!! Denken Sie daran, nur weil Sie etwas tun können, heißt das nicht, dass Sie es tun sollten.

Externe Referenzen

Deftype-Anweisungen (VBA)Office VBA-ReferenzthemaMicrosoft Docso365devx Windows-API-Deklarationen in VBA für 64-BitSo konvertieren Sie Ihre API-Deklarationen in 64-Bit. - Gängige Mythen entlarvt, Schlüsselfaktoren erklärt!CodekabinettPhilipp Stiefel

Referenzierte Artikel

Respekt vor AbwärtskompatibilitätEine Funktion, die von einem sehr kleinen Prozentsatz von Power-Usern stark genutzt wurde, wurde im Laufe von fünf nachfolgenden Upgrades (und Zählen) beibehalten. Nun, das zeigt Respekt vor der Abwärtskompatibilität. Mike Wolfe nicht mehr gesetzt RegOp-Klasse für 64-Bit-VBAUAktualisierung eines klassischen Lese- und Schreibklassenmoduls für die VBA-Registrierung für 64-Bit-Kompatibilität. Mike Wolfe nicht mehr gesetzt