2

VB6 レガシー DLL を参照する .NET アプリケーションがあります。レガシ DLL には、パブリック メソッドを持つクラスがあります。このパブリック メソッド内では、既存のフォームを名前で検索するか、存在しない場合は作成しようとしています。

Set objForm = GetForm(strFormName)

If objForm Is Nothing Then

    'Creates a new instance of the form
    Set objForm = VB.Forms.Add(strFormName)

End If

...場所GetFormは次のとおりです。

Private Function GetForm(ByVal strFormName As String) As Form

    Dim objForm As Form

    For Each objForm In VB.Forms
        If objForm.Name = strFormName Then
            Set GetForm = objForm
            Exit Function
        End If
    Next

    Set GetForm = Nothing

End Function

この行でエラーが発生しています:

Set objForm = VB.Forms.Add(strFormName)

エラーは次のとおりです。

Automation error
The object invoked has disconnected from its clients.   
Error#-2147417848(80010108)

strFormNameは有効なフォーム名であり、この public メソッド呼び出しはほぼ常に機能することに注意してください。このエラーが発生することは非常にまれです。

このエラーの原因を知りたいのですが、さらに追跡するために他に何ができますか?

4

2 に答える 2

6

@Dabblernl がリンクした KB 記事は、この問題に非常に関連していますVB.Forms コレクションは、まさにそのような非修飾参照です。これはグローバル変数のように機能し、オブジェクト参照を提供しなくても、VB6 コードのどこでも VB.Forms を使用できます。

内部的には、VB6 ランタイムは、初めてフォームを作成したときに Forms コレクションを作成し、このコレクション オブジェクトを格納して、VB.Forms への今後の参照でまったく同じコレクションを使用できるようにします。エラー コードが意味するのは、そのコレクションが破棄された後に使用されているということです。

それがいつ発生するかは明確ではありません。これはすべて、VB6 ランタイム サポート ライブラリの内部配管です。ただし、通常、最後のフォームがアンロードされると、VB6 アプリは終了します。あなたの場合の違いは、プロセスの有効期間が VB6 ランタイムによって制御されなくなったことです。.NET がそれを制御します。

したがって、外挿すると、VB6 ランタイムが Forms コレクションが不要であると判断して破棄し、後で .NET コードが新しい Form を作成してエラーを引き起こす可能性があります。

これがまったく正確な場合は、これを防ぐための対策を講じる必要があります。これを行う 1 つの可能な方法は、コレクションを有効に保つために少なくとも 1 つの VB6 フォームが常に存在するようにすることです。目に見えるものである必要はありません。

于 2013-02-21T03:14:15.197 に答える
1

問題が断続的であり、OP に記載されているようにめったに発生しない場合は、再試行すると回避できる場合があります。

Public Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)

Public Sub SomeProcedure()
Dim attempts As Integer
On Error Goto ErrHandler

    Set objForm = GetForm(strFormName)
    If objForm Is Nothing Then

        'Creates a new instance of the form
        Set objForm = VB.Forms.Add(strFormName)

    End If

ErrHandler:
    If Err.Number = -2147417848 Then
        attempts = attempts + 1
        If attempts < 10 Then
            Err.Clear
            Sleep 55
            Debug.Print "Automation error. Retry attempt: " & attempts
            Resume
        End If
    End If
    If Err.Number <> 0 Then 'this should run after the 10th failed attempt
        MsgBox Err.Message
        Err.Clear
    End If
End Sub

問題が解決するわけではありませんが、それが原因でアプリがクラッシュするのを防ぐことができます...

于 2013-02-16T16:40:08.633 に答える