[AccessD] Broken References in Runtime AXP

Gustav Brock gustav at cactus.dk
Sat Jul 19 01:11:42 CDT 2003


Hi Charlotte

That is sad as it confirms that this behaviour has not changed - not
to say improved - since A97.

If you remove that conditional check (If IsCompiled ..) and "force"
the compilation by running the SysCmd call, does your app report
itself as compiled?

I've never succeeded in A97 by this method as it seems (to me, others
have reported success) that the code cannot call a compilation of
itself; you have to make the call manually from either the debug
window or a macro or open a form with a timer to "cut" the connection
between the verification code and the compilation code. This form can
be the opening form or a special form for this purpose which when it
closes opens the normal opening form.

This is how I do; the form is unbound and has no controls except the
checkbox with a default value of False:

<code>

Private Sub Form_Activate()
  
  ' Validate References.
  Me!chkChecked = VerifyReferences(True)
  
  ' At this point, this application will be not compiled.

End Sub


Private Sub Form_Timer()

' Let a timer compile the current app after a forced verification of
' the references which will leave the app not compiled.
'
' 2000-02-01. Cactus Data ApS. CPH.

  ' Maximum number of times this check will be carried out before
  ' the form will be closed even if the application is not compiled.
  Const cintRoundTripsMax As Integer = 10
  
  Static intRoundTrips    As Integer

  Debug.Print Time, Me!chkChecked, intRoundTrips

  If Me!chkChecked = True Or intRoundTrips > cintRoundTripsMax Then
    ' After tampering with the references the application appears to be
    ' compiled, which it is not.
    ' This call will not fail even if the application is compiled or
    ' appears to be.
    '
    ' Compile and Save All Modules.
    ' The command:
    '   Application.RunCommand acCmdCompileAndSaveAllModules
    ' can not be used. Thus, use undocumented SysCmd() call.
    Call SysCmd(504, 16483)
    '
    ' Close form.
    DoEvents
    DoCmd.Close acForm, Me.Name
  Else
    ' Check of references is still going on or an error may have occurred.
    ' And maximum number of roundtrips has not been reached.
    intRoundTrips = intRoundTrips + 1
  End If

End Sub

</code>

/gustav


> I was just reviewing this and noticed that last bit using IsCompiled.
> That's another property I found to be flakey.  The compile will run, but
> the IsCompiled property tends to report the app is compiled even after
> changing a reference.

> Charlotte Foust

> -----Original Message-----
> From: Gustav Brock [mailto:gustav at cactus.dk] 
> Sent: Friday, July 18, 2003 2:43 AM
> To: Access Developers discussion and problem solving
> Subject: Re: [AccessD] Broken References in Runtime AXP


> Hi Charlotte

>> Um, with a broken reference, you have to substitute the numeric value 
>> of constants in your code, and even then you can get odd results.  For

>> example SysCmd(acSysCmdRuntime) or its numeric equivalent don't seem 
>> to recognize a runtime session.  Anyhow, I substituted equivalents and

>> still didn't get a reliable result.  For one thing, the VBA.Dir 
>> command didn't seem to always like the FullPath.  When I stepped 
>> through the code in a normal session, Dir returned a value greater 
>> than zero for the FullPath even though the file isn't there and the 
>> IsBroken property at that point reported True, which is correct.  
>> Heaven knows what happens in runtime though because it wasn't working.

>> The only thing I've found that does seem to work is to use Dir to test
>> the parsed out path and filename to see if it exists, so maybe there's
>> a null character at the end of FullPath.  And even that seems to
>> return spotty results.  I works when I step through it but doesn't 
>> always work at runtime.  What really looks weird is that the reference
>> object seems to sometimes return a correct path for the broken
>> reference, even though the reference itself points elsewhere!

>> Sorry, I have to go now.  They're coming to take me away ....

> They refused to take you, right?

> But have you to tried to _force_ Access to validate the references?
> Again, I haven't worked with this for Access XP but for A97 you could
> have to do this. Here's a function I have used for that:

> <code>

> Public Function VerifyReferences( _
>   ByVal booErrorDisplay As Boolean) As Boolean
>
> ' Verify Access' external references and re-establish these if possible.
> ' Uses function IsBroken97(). ' ' 2001-07-29. Cactus Data ApS, CPH.
>
>   Dim refA                    As Access.Reference
>   Dim refX                    As Access.Reference
>   Dim strRefFullPath          As String
>   Dim booNotBuiltInRefExists  As Boolean
>   Dim booIsBroken             As Boolean
>   Dim booRefIsMissing         As Boolean
>   Dim strMsgTitle             As String
>   Dim strMsgPrompt            As String
>   Dim strMsgHeader            As String
>   Dim strMsgFooter            As String
>   Dim lngMsgStyle             As Long
>
>   ' No special error handling.
>   On Error Resume Next
>
>   ' User oriented error message.
>   strMsgTitle = "Missing support file"
>   strMsgHeader = "One or more supporting files are missing:" & vbCrLf
>   strMsgFooter = vbCrLf & vbCrLf & "Report this to IT support." & vbCrLf
>   strMsgFooter = strMsgFooter & "Program execution cannot continue."
>   lngMsgStyle = vbCritical + vbOKOnly
>
>   ' Look for the first reference in the database other than
>   ' the built in "Access" and "Visual Basic for Applications".
>   For Each refA In Access.Application.References
>     If refA.BuiltIn = False Then
>       ' At least one not built in reference is in use.
>       booNotBuiltInRefExists = True
>       ' Check if the reference is not broken.
>       If IsBroken97(refA) = False Then
>         ' The first not missing not built in reference is found.
>         Set refX = refA
>         Exit For
>       End If
>     End If
>   Next
>
>   If booNotBuiltInRefExists = False Then
>     ' Only built in references are in use.
>     ' Nothing more to do.
>   Else
>     If refX Is Nothing Then
>       ' All not built in references are missing.
>       ' Don't remove missing references as there is no way to
>       ' re-establish a reference if its identity is lost.
>     Else
>       ' Remove this not built in reference and add it back to
>       ' force Access to revalidate all references.
>       ' This may or may not rebuild links to missing references.
>       With Access.Application.References
>         strRefFullPath = refX.FullPath
>         .Remove refX
>         .AddFromFile strRefFullPath
>       End With
>       Set refX = Nothing
>     End If
>     ' Check references if any should be missing.
>     ' If so, no attempt to read a reference is done as it most likely
>     ' either is not installed or has been moved to an unknown directory.
>     For Each refA In Access.Application.References
>       booIsBroken = IsBroken97(refA)
>       If booIsBroken = True Then
>         ' Build list of missing files.
>         strMsgPrompt = strMsgPrompt & vbCrLf & refA.FullPath
>       End If
>       booRefIsMissing = booRefIsMissing Or booIsBroken
>     Next
>
>     ' If any reference is broken, display error message if requested.
>     If booRefIsMissing = True And booErrorDisplay = True Then
>       strMsgPrompt = strMsgHeader & strMsgPrompt & strMsgFooter
>       Access.Application.DoCmd.Beep
>       VBA.MsgBox strMsgPrompt, lngMsgStyle, strMsgTitle
>     End If
>   End If
>
>   Set refA = Nothing
>
>   ''' This should work but doesn't. ------------------------------
>   ' If References have been updated, the application is left decompiled.
>   If Not Access.Application.IsCompiled Then
>     ' Compile application.
>     Call Access.Application.SysCmd(504, 16483)
>   End If
>   ''' ------------------------------------------------------------
>
>   VerifyReferences = Not booRefIsMissing
>
> End Function
>
> </code>
>
> /gustav


>> Interesting and scaring.
>> Does this mean that the old A97 bug is still alive two versions 
>> later??

>> Would you mind testing the function below to verify if this is still 
>> so?


>> <code>

>> Public Function IsBroken97(ByVal ref As Access.Reference) As Boolean

>> ' Alternative method to check if a reference is broken
>> ' as the IsBroken property cannot be used in Access97.
>> '
>> ' 2000-03-19. Gustav Brock. Cactus Data ApS.

>> ' Refer to this article at Microsoft Technet:
>> '
>> ' Article ID: Q186720
>> '
>> ' The information in this article applies to:
>> ' Microsoft Access 97
>> '
>> ' SYMPTOMS
>> ' In Microsoft Access, IsBroken is a property of the References 
>> collection. ' The Microsoft Access Help topic on the Isbroken property

>> states the following: ' ' The IsBroken property returns a Boolean 
>> value indicating whether a ' Reference object points to a valid 
>> reference in the Windows Registry. ' ' Although this statement is 
>> correct, to receive this Boolean value ' you must trap for errors that

>> are generated by the broken reference. ' Also, the IsBroken property 
>> becomes True only when the file being referenced ' is deleted and the 
>> Microsoft Windows Recycle Bin is emptied. ' This article details the 
>> steps necessary to receive the Boolean value.

>>   Dim booRefOK As Boolean
>>   On Error GoTo Err_IsBroken97
  
>>   If Len(Dir(ref.FullPath, vbNormal)) > 0 Then
>>     booRefOK = Not ref.IsBroken
>>   End If

>> Exit_IsBroken97:
>>   IsBroken97 = Not booRefOK
>>   Exit Function

>> Err_IsBroken97:
>>   ' Ignore non existing servers, drives, and paths.
>>   Resume Exit_IsBroken97
  
>> End Function

>> </code>

>> /gustav


>>> Yes, but I've tracked down the problem ... Or at least one of them.  
>>> I

>>> had taken it on faith that the BrokenReference method would actually
>>> return a -1 when a reference to another database was missing and that

>>> the IsBroken property of the reference object would return a -1 in 
>>> that case as well.  Apparently, even fully disambiguated, that isn't 
>>> true. Now I need to figure out how to NOT run it every time the 
>>> application starts!  I had to resort to writing directly to a text 
>>> file to figure out where it was going haywire.



More information about the AccessD mailing list