2010-10-01 19 views
0

Y a-t-il des moyens dans Access VBA (2003) de transformer une référence COM en entier et d'appeler AddRef/Release? (qui donne l'erreur "Fonction ou interface marqué comme restreint, ou la fonction utilise un type Automation non pris en charge dans Visual Basic")Accès: conserver une référence COM à travers la réinitialisation du programme?

J'utilise un objet COM tiers qui ne gère pas être instancié deux fois dans Visual Basic un seul processus (c'est un bug connu). J'ai donc pensé à stocker la référence comme légende d'un contrôle sur un formulaire caché pour le protéger de la réinitialisation du programme effaçant toutes les variables VB.

Édition: Je pense que la conversion en int peut être effectuée avec ObjPtr non documenté, et de nouveau avec l'API CopyMemory, et AddRef/Release peut être appelée implicitement. Mais y a-t-il une meilleure façon? Les compléments sont-ils protégés contre la réinitialisation du programme?

Répondre

0

Est-ce que le problème est de survivre à la réinitialisation du code ou est-ce qu'une fois le code réinitialisé, il ne peut pas être réinitialisé?

Pour le premier problème, enveloppez votre objet de niveau supérieur dans une fonction et utilisez une variable STATIC en interne pour mettre en cache la référence. Si la variable STATIC est Nothing, réinitialisez-la. Voici la fonction que j'utilise pour la mise en cache une référence à la base de données locale:

Public Function dbLocal(Optional bolInitialize As Boolean = True) + 
    As DAO.Database 
    ' 2003/02/08 DWF added comments to explain it to myself! 
    ' 2005/03/18 DWF changed to use Static variable instead 
    ' uses GoTos instead of If/Then because: 
    ' error of dbCurrent not being Nothing but dbCurrent being closed (3420) 
    ' would then be jumping back into the middle of an If/Then statement 
    On Error GoTo errHandler 
    Static dbCurrent As DAO.Database 
    Dim strTest As String 

    If Not bolInitialize Then GoTo closeDB 

    retryDB: 
    If dbCurrent Is Nothing Then 
     Set dbCurrent = CurrentDb() 
    End If 
    ' now that we know the db variable is not Nothing, test if it's Open 
    strTest = dbCurrent.Name 

    exitRoutine: 
    Set dbLocal = dbCurrent 
    Exit Function 

    closeDB: 
    If Not (dbCurrent Is Nothing) Then 
     Set dbCurrent = Nothing 
    End If 
    GoTo exitRoutine 

    errHandler: 
    Select Case err.Number 
     Case 3420 ' Object invalid or no longer set. 
     Set dbCurrent = Nothing 
     If bolInitialize Then 
      Resume retryDB 
     Else 
      Resume closeDB 
     End If 
     Case Else 
     MsgBox err.Number & ": " & err.Description, vbExclamation, "Error in dbLocal()" 
     Resume exitRoutine 
    End Select 
    End Function 

Partout où vous souhaitez l'un de ces dans le code:

Dim db As DAO.Database 
    Set db = CurrentDB() 
    Set db = DBEngine(0)(0) 
    db.Execute "[SQL DML]", dbFailOnError 

... vous pouvez remplacer le tout avec:

dbLocal.Execute "[SQL DML]", dbFailOnError 

... et vous n'avez pas à vous soucier de l'initialisation lorsque votre application ouvre, ou après une remise à zéro du code - il est auto-guérison, car il vérifie la variable interne statique et réinitialise si nécessaire. Le seul inconvénient est que vous devez passer un appel avec l'argument bolInitialize défini sur False lorsque vous arrêtez votre application, car cela nettoie la référence afin qu'il n'y ait aucun risque de blocage de votre application lorsqu'elle est hors de portée. l'application se ferme.

Pour l'autre problème, je doute vraiment qu'il y ait une solution dans VBA, sauf si vous pouvez faire un appel d'API et tuer le processus externe. Mais c'est un peu long, je pense.

+0

C'est le deuxième problème. En outre, il s'agit d'un objet COM in-process, il n'est donc pas question de "tuer le processus externe". –

+0

BTW si vous commencez vos commentaires de code avec '' # alors ils sont valides dans VB * et * semblent raisonnables dans la démarque. –

+0

Les commentaires me semblent très bien dans markdown. Et # n'est pas un caractère de commentaire valide dans VBA. –