如何从失去与(本地托管的)DCOM对象的连接中恢复?

时间:2016-04-28 13:50:50

标签: vb.net dcom

(我不确定这是否更适合代码审查)

我使用在内部维护DCOM连接的(闭源)库,此DCOM连接转到本地计算机上运行的服务。用户(而不是通过我们的应用程序)经常停止并启动此服务。

不幸的是,看起来DCOM相关的异常会影响到我们的应用程序。

似乎没有任何方式在库中给出以确定与服务的连接是否仍然有效,现在只知道我们已经失去与服务的连接以尝试做某事并让它抛出异常(其类型变化很大)。

尝试使其更易于管理的最佳尝试是将通常由DCOM引起的异常与由配置问题引起的异常分开....

以下是代码最终结果的样本:

Private Sub Initialize()
    Dim ParametersToDComObject As Integer

    Try
        Dim HRESULT = ClassThatUsesDCOMInstance.InitDCOMObject(ParametersToDComObject)
        Console.WriteLine("Connected to service through DCOM.")

    Catch Ex As Exception
        If (IsLikelyCausedByConnectionLoss(Ex)) Then
            'in this case, throw to make sure that we don't try to continue assuming that the connection went through

            'I'm not sure what type of exception would be best to throw here,
            'this would occur if the service is not running; the calling function
            'would notify the user that there's a problem
            Throw New InvalidOperationException(Ex.Message, Ex)

        Else
            Throw


        End If

    End Try

End Sub

Private Sub ReadDataFromClass(EntryName As String)
    Try
        Dim HRESULT As Integer = ClassThatUsesDCOMInstance.ReadEntry(EntryName)

    Catch Ex As Exception
        If (IsLikelyCausedByConnectionLoss(Ex)) Then
            'If the service is stopped, from the application's perspective every method in 
            'this class suddenly starts failing, and it won't start working again until a new instance 
            'of the class that uses DCOM is made.
            '
            'So the sub below attempts to make sure that our application knows that the methods in this class
            'won't work anymore... (I usually set ClassThatUsesDCOMInstance to Nothing after cleaning up)
            '
            'Sometimes I just have to "reconnect", but the tricky thing is, the only recovery option may be to
            '(re)start the service that's providing the DCOM object; it seems best to notify the
            'user in this case since in most cases the user knowlingly stopped the service, it's
            'normal to stop the service to configure it
            CleanupAfterConnectionLoss()
            Throw New InvalidOperationException(Ex.Message, Ex)
        End If

        If (TypeOf (Ex) Is TheLibraryDefinedThisException) Then
            'let's say that the library throws this if we try to read an entry that doesn't exist (e.g., if the configuration has changed)
            'we can't fix the problem automatically, but we can notify the user that something has changed external to this program, so they can
            'either fix the service or edit their configuration for our application
            Console.WriteLine("Entry " & EntryName & " could not be read " & Ex.Message & " check that the entry is defined on the service")

        Else
            Throw

        End If

    End Try
End Sub




Private Function IsLikelyCausedByConnectionLoss(ThrownException As Exception) As Boolean
    'I'm thinking it's best to put this in a separate function because development has gone like this:
    '
    ' 1. the provided documentation does not give any information about what methods will throw what kinds of exceptions
    '    All functions return **HRESULTs**, I assumed that there weren't going to be /any/ exceptions
    '   
    '   It turns out the HRESULTs cover certain errors and exceptions cover certain errors, with some overlap...
    '
    ' 2. I determined experimentally during testing that it throws a <Library Defined Exception> if I give it an invalid entry name, okay, I can work with that
    '
    ' 3. I determined experimentally that if I stop the service while we're connected, all functions throw a COMException, not convenient but ok.
    '
    ' 4. Weeks later, I figure out that it also occasionally throws InvalidComObjectException if the service is stopped under the same situation
    '
    ' 5. Weeks later, I find out that it occasionally throws ApplicationExceptions under the same situation
    '
    ' 6. Weeks later, I find out that certain functions will additionally throw an InvalidCastException
    '
    ' note that there's no change in input to the library to cause these different exceptions, and the only cause
    ' is the loss of connection to the DCOM server
    '
    ' in the last code setup I had to manually update every try/catch block that had anything to do with this library every time
    ' I found something new...

    If (TypeOf (ThrownException) Is InvalidCastException) Then
        'I really don't like catching this, but I get this if the COM object fails to bind to the interface,
        'which occasionally happens if the service isn't there or isn't set up right
        Return True

    ElseIf (TypeOf (ThrownException) Is ApplicationException) Then
        'I really don't like catching this either, same reason as above
        Return True

        'I don't believe this is an exhaustive list of every exception that can be thrown due to loss of DCOM connection,
        'please let me know if you know of more exceptions that can be thrown...

    ElseIf (TypeOf (ThrownException) Is Runtime.InteropServices.COMException) Then
        Return True

    ElseIf (TypeOf (ThrownException) Is Runtime.InteropServices.InvalidComObjectException) Then
        Return True

    Else
        Return False

    End If

End Function
但是,我觉得这对于这个问题来说是一个糟糕的解决方案。这似乎不仅仅是吞下所有例外情况,而且不是太多。

  • 是否存在包含所有可能的DCOM错误的异常?
  • 或者,是否有其他方法可以检测到与服务的连接已丢失?

编辑:

  • 这种情况对于.NET中的DCOM是典型的吗?

0 个答案:

没有答案