我有一个引用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
是有效的表单名称,此公共方法调用几乎始终 。它偶尔会发生这种错误。
我想知道导致此错误的原因,或者我还能做些什么来进一步追踪它?
答案 0 :(得分:6)
@Dabblernl链接的KB article与此问题非常相关。 VB.Forms集合正是这样一个不合格的引用。它就像一个全局变量,你可以在VB6代码中的任何地方使用VB.Forms而不提供对象引用。
在幕后,VB6运行时在您第一次创建表单并存储此集合对象时创建Forms集合,以便将来对VB.Forms的引用使用完全相同的集合。错误代码的含义是您在销毁之后使用该集合。
目前还不是很清楚何时发生这种情况,这是VB6运行时支持库的所有内部管道。但通常情况下,VB6应用程序会在最后一个表单卸载时终止。在您的情况下有所不同的是,您的进程的生命周期不再受VB6运行时控制。 .NET现在控制它。
因此,推断,很有可能VB6运行时已经决定不再需要Forms集合并将其销毁,并且您的.NET代码可能会创建一个新表单,从而触发错误。
如果这完全准确,那么您需要采取对策来防止这种情况发生。一种可行的方法是确保始终至少有一个VB6表单以保持集合有效。它不一定是可见的。
答案 1 :(得分: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
它没有解决问题,但它可能会因为它而停止你的应用程序崩溃......