错误-2147417848位于VB.Forms.Add通过COM调用
我有一个.NET应用程序,它引用了VB6遗留DLL。旧DLL有一个带有公共方法的类。在该公共方法中,它试图按名称查找现有表单,如果不存在,则创建该表单:错误-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
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并重新加载它,但我认为这是不可能的。