错误-2147417848位于VB.Forms.Add通过COM调用

错误-2147417848位于VB.Forms.Add通过COM调用,com,vb6,Com,Vb6,我有一个.NET应用程序,它引用了VB6遗留DLL。旧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是: P

我有一个.NET应用程序,它引用了VB6遗留DLL。旧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
是一个有效的表单名称,并且此公共方法调用几乎一直有效。只是偶尔会出现这种错误


我想知道是什么导致了这个错误,或者我还可以做些什么来进一步追踪它?

如果问题是间歇性的,并且很少像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
Public声明子睡眠库“kernel32”(ByVal-dwms长度)
公共子程序()
将尝试设置为整数
关于错误转到错误处理程序
Set objForm=GetForm(strFormName)
如果objForm什么都不是,那么
'创建窗体的新实例
设置objForm=VB.Forms.Add(strFormName)
如果结束
错误处理程序:
如果错误号=-2147417848,则
尝试次数=尝试次数+1
如果尝试次数小于10,则
呃,明白了
睡55
Debug.Print“自动错误。重试尝试:”&尝试
简历
如果结束
如果结束
如果错误号为0,则“这应在第10次失败尝试后运行”
MsgBox错误消息
呃,明白了
如果结束
端接头
这并不能解决问题,但它可能会阻止你的应用程序因为它而崩溃。

与@Dabblernl链接的内容与此问题非常相关。Forms集合正是这样一个非限定引用。它就像一个全局变量,您可以在VB6代码中的任意位置使用VB.Forms,而无需提供对象引用

在后台,VB6运行时在您第一次创建窗体时创建窗体集合,并存储此集合对象,以便将来对VB.Forms的引用使用完全相同的集合。错误代码的意思是,您在该集合被销毁后使用它

具体什么时候发生这种情况还不是很清楚,这都是VB6运行时支持库的内部管道。但通常,VB6应用程序在最后一个窗体卸载时终止。与您的情况不同的是,进程的生存期不再由VB6运行时控制。NET现在控制它

因此,从外推的角度来看,VB6运行时很有可能决定不再需要表单集合并将其销毁,并且.NET代码稍后可能会创建一个新表单,从而触发错误


如果这是准确的,那么你需要采取相应的措施来防止这种情况发生。一种可能的方法是确保始终至少有一个VB6表单用于保持集合的有效性。它不必是可见的。

你知道这篇文章吗@是的,我看到了。我认为这不适用。我使用的是完全限定的引用(
VB.Forms.Add
)。它也在谈论它第一次工作并在随后的调用中失败,但这在第一次、第二次、第三次工作,但有时只是随机失败。你有任何
Global
s吗?@retailcoder-是的,有遗留的全局变量。我认为它们都是基本类型(
Integer
,等等),我会尝试一下,但似乎一旦发生这种情况,它将是永久的,直到您重新启动应用程序。然后闻起来好像是
VB.Forms
对象断开了连接。如果是这样的话,请考虑从一个“开销观察员”启动这个程序,这样可以启动一个新的新实例(也许是用命令行ARG来恢复一些状态)。在此找到线索:此VB6 dll将自身暴露为COM对象,并从.NET代码运行。它每次调用上面的代码时都会更新COM对象。我认为“重新启动”它的唯一方法是以某种方式卸载DLL并重新加载它,但我认为这是不可能的。