2013-02-12 3 views
2

У меня есть приложение .NET, которое ссылается на устаревшую DLL VB6. Унаследованная DLL имеет класс с общедоступным методом. Внутри этого открытого метода он пытается найти существующую форму по имени, или создать его, если он не существует:Ошибка -2147417848 на VB.Forms.Add call over COM

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 является действительным именем формы, и этот открытый вызов метода работает почти все время. Это очень редко случается, чтобы поднять эту ошибку.

Я хотел бы знать, что вызывает эту ошибку, или что еще можно сделать, чтобы отслеживать ее дальше?

+1

Вы знаете об этой статье? http://support.microsoft.com/default.aspx?scid=kb;en-us;Q319832 – Dabblernl

+0

@Dabblernl - да, я это видел. Я не думаю, что это применимо. Я использую полностью квалифицированную ссылку ('VB.Forms.Add'). Это также говорит о том, что он работает в первый раз и не работает при последующих вызовах, но это работает сначала, во-вторых, в третий раз, но иногда просто случайно. –

+0

У вас есть '' Global's? –

ответ

6

KB article, что связанный @Dabblernl очень относится к этой проблеме. Коллекция VB.Forms - это точно такая неквалифицированная ссылка. Он действует как глобальная переменная, вы можете использовать VB.Forms в любом месте кода VB6, не предоставляя ссылку на объект.

Под капотом, среда выполнения VB6 создает коллекцию форм в первый раз, когда вы создаете форму и сохраняет этот объект коллекции, чтобы в будущих ссылках на VB.Forms была использована одна и та же коллекция. Что означает код ошибки, так это то, что вы используете эту коллекцию после ее уничтожения..

Непонятно, когда это происходит, это все внутренняя сантехника для библиотеки поддержки времени исполнения VB6. Но обычно приложение VB6 прекращается, когда последняя форма выгружается. В вашем случае другое дело, что срок службы вашего процесса больше не контролируется средой исполнения VB6. Теперь .NET управляет им.

Итак, экстраполируя, есть хорошие шансы, что среда исполнения VB6 решила, что коллекция форм больше не нужна и уничтожила ее, а ваш код .NET может создать новую форму позже, тем самым вызывая ошибку.

Если это абсолютно точно, вам нужно будет принять контрмер, чтобы это не происходило. Один из возможных способов сделать это - убедиться, что всегда существует, по крайней мере, одна форма VB6, чтобы сохранить коллекцию действительной. Это не должно быть видимым.

1

Если проблема прерывистый и очень редко, как указано в ОП, может повторить попытку работать вокруг него:

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 

Это не решает проблему, но это может остановить приложение от сбой из-за этого ...

+0

Я попробую, но кажется, что как только это произойдет, оно будет постоянно, пока вы не перезапустите приложение. –

+0

Тогда это пахнет, так как объект 'VB.Forms' отключен *. Если это так, подумайте о том, чтобы запустить эту программу из «наблюдателя накладных расходов», которая может начать новый новый экземпляр (возможно, с помощью команд командной строки для восстановления некоторого состояния), когда это произойдет (возможно, поймать конкретное исключение). Найденные подсказки здесь: http://stackoverflow.com/questions/4579348/how-to-rerun-my-program-in-vb6 –

+0

Эта DLL VB6 подвергает себя как COM-объект и выполняется из .NET-кода. Это новый объект COM каждый раз, когда он вызывает код выше. Я думаю, что единственный способ «перезапустить» - это как-то выгрузить DLL и перезагрузить его, но я не думаю, что это возможно. –

Смежные вопросы