Domanda

ho un app VB6 che chiamerà il mencoder.exe che fa parte del MPlayer per convertire alcuni file in formato FLV. Mi viene questo strano problema eccezione non gestita da mencoder Ogni volta che provo per convertire questo file uno OpenDivX.

Al momento, io sono poco chiaro se è questo codec è il colpevole dietro questo. In entrambi i casi ho tentare di modificare la riga di comando e anche scaricato l'ultima versione disponibile per mencoder.

in modo che la conversione funziona bene e l'unico problema è che il mencoder andrà in crash, alla fine, come il file video supera in qualche modo al 100% al 102%. quindi la mia domanda è come faccio percorso questa eccezione a essere gestita dal mio VB6 app in modo che il popup errore di brutto non verrà mostrato?

Ho anche incluso la cattura eccezione nel codice, ma non è la cattura di tale eccezione.

    ' Function GetCommandOutput
'
' sCommandLine:  [in] Command line to launch
' blnStdOut        [in,opt] True (defualt) to capture output to STDOUT
' blnStdErr        [in,opt] True to capture output to STDERR. False is default.
' blnOEMConvert:   [in,opt] True (default) to convert DOS characters to Windows, False to skip conversion
'
' Returns:       String with STDOUT and/or STDERR output
'
Public Function GetCommandOutput(sCommandLine As String, _
                                 Optional blnStdOut As Boolean = True, _
                                 Optional blnStdErr As Boolean = False, _
                                 Optional blnOEMConvert As Boolean = True, _
                                 Optional encoderType As String) As String

    Dim hPipeRead   As Long, hPipeWrite1 As Long, hPipeWrite2 As Long
    Dim hCurProcess As Long
    Dim sa          As SECURITY_ATTRIBUTES
    Dim si          As STARTUPINFO
    Dim pi          As PROCESS_INFORMATION
    Dim baOutput()  As Byte
    Dim sNewOutPut  As String
    Dim lBytesRead  As Long
    Dim fTwoHandles As Boolean
    Dim lRet        As Long

    Const BUFSIZE = 1024      ' pipe buffer size

    On Error GoTo ErrorHandler

    ' At least one of them should be True, otherwise there's no point in calling the function
    If (Not blnStdOut) And (Not blnStdErr) Then
        Err.Raise 5         ' Invalid Procedure call or Argument
    End If

    ' If both are true, we need two write handles. If not, one is enough.
    fTwoHandles = blnStdOut And blnStdErr
    ReDim baOutput(BUFSIZE - 1) As Byte

    With sa
        .nLength = Len(sa)
        .bInheritHandle = 1    ' get inheritable pipe handles
    End With

    If CreatePipe(hPipeRead, hPipeWrite1, sa, BUFSIZE) = 0 Then

        Exit Function

    End If

    hCurProcess = GetCurrentProcess()
    ' Replace our inheritable read handle with an non-inheritable. Not that it
    ' seems to be necessary in this case, but the docs say we should.
    Call DuplicateHandle(hCurProcess, hPipeRead, hCurProcess, hPipeRead, 0&, 0&, DUPLICATE_SAME_ACCESS Or DUPLICATE_CLOSE_SOURCE)

    ' If both STDOUT and STDERR should be redirected, get an extra handle.
    If fTwoHandles Then
        Call DuplicateHandle(hCurProcess, hPipeWrite1, hCurProcess, hPipeWrite2, 0&, 1&, DUPLICATE_SAME_ACCESS)
    End If

    With si
        .cb = Len(si)
        .dwFlags = STARTF_USESHOWWINDOW Or STARTF_USESTDHANDLES
        .wShowWindow = SW_HIDE          ' hide the window

        If fTwoHandles Then
            .hStdOutput = hPipeWrite1
            .hStdError = hPipeWrite2
        ElseIf blnStdOut Then
            .hStdOutput = hPipeWrite1
        Else
            .hStdError = hPipeWrite1
        End If

    End With

    Dim totalSeconds As Double

    If CreateProcess(vbNullString, sCommandLine, ByVal 0&, ByVal 0&, 1, 0&, ByVal 0&, vbNullString, si, pi) Then
        ' Close thread handle - we don't need it
        Call CloseHandle(pi.hThread)
        ' Also close our handle(s) to the write end of the pipe. This is important, since
        ' ReadFile will *not* return until all write handles are closed or the buffer is full.
        Call CloseHandle(hPipeWrite1)
        hPipeWrite1 = 0

        If hPipeWrite2 Then
            Call CloseHandle(hPipeWrite2)
            hPipeWrite2 = 0
        End If

        Do

            ' Add a DoEvents to allow more data to be written to the buffer for each call.
            ' This results in fewer, larger chunks to be read.
            'DoEvents
            If ReadFile(hPipeRead, baOutput(0), BUFSIZE, lBytesRead, ByVal 0&) = 0 Then

                Exit Do

            End If

            If blnOEMConvert Then
                ' convert from "DOS" to "Windows" characters
                sNewOutPut = String$(lBytesRead, 0)
                Call OemToCharBuff(baOutput(0), sNewOutPut, lBytesRead)
            Else
                ' perform no conversion (except to Unicode)
                sNewOutPut = Left$(StrConv(baOutput(), vbUnicode), lBytesRead)
            End If

            GetCommandOutput = GetCommandOutput & sNewOutPut
            ' If you are executing an application that outputs data during a long time,
            ' and don't want to lock up your application, it might be a better idea to
            ' wrap this code in a class module in an ActiveX EXE and execute it asynchronously.
            ' Then you can raise an event here each time more data is available.
            'Debug.Print sNewOutPut + vbNewLine

            If encoderType = "ffmpeg" Then
                If totalSeconds < 1 Then
                    totalSeconds = GetFFmpegFileTotalSeconds(sNewOutPut)
                End If

                Call CalculateFFMpegProgress(sNewOutPut, totalSeconds)
            Else
                Call CalculateMencoderProgress(sNewOutPut)
            End If

            'RaiseEvent OutputAvailable(sNewOutput)
        Loop

        ' When the process terminates successfully, Err.LastDllError will be
        ' ERROR_BROKEN_PIPE (109). Other values indicates an error.
        Call CloseHandle(pi.hProcess)
    Else
        GetCommandOutput = "Failed to create process, check the path of the command line."
    End If

    ' clean up
    Call CloseHandle(hPipeRead)

    If hPipeWrite1 Then
        Call CloseHandle(hPipeWrite1)
    End If

    If hPipeWrite2 Then
        Call CloseHandle(hPipeWrite2)
    End If
    Exit Function

ErrorHandler:
    Call WriteErrorLog(Err, "Class clsThread : Sub GetCommandOutput")
End Function

Aggiornamenti:

e nel caso in cui voi ragazzi siete curiosi ciò che l'applicazione è stata l'output quando si crash, eccolo qui:

1 frame duplicato (s)!

Pos: 83.2s 2504f (99%) 112.65fps Trem: 0min 6MB A-V: 0.008 [571: 79]] 1 frame duplicato (s)!

Pos: 83.4s 2510f (102%) 112.74fps Trem: 0min 6MB A-V: 0.006 [571: 79] 1 frame duplicato (s)!

Pos: 83.6s 2516f (102%) 112.84fps Trem: 0min 6MB A-V: 0.004 [571: 79] 1 frame duplicato (s)!

[MPEG4 @ 0x1ac53a0] occultare 40 cc, 40 AC, 40 MV errori A-V: 0.003 [571: 79]

alt text http://img21.imageshack.us/img21/4539/exception .png

grazie:)

È stato utile?

Soluzione

Si potrebbe provare a utilizzare l'API SetUnhandledExceptionFilter per catturare l'eccezione. L'ho usato in precedenza, ma solo con un successo limitato. Credo che questo codice di origine o di provenienza, è stato fortemente influenzato dal, o è stato ispirato da un articolo del maggio 99 visiva programmatori di base ufficiale chiamato "Nessun errori di eccezione, caro Dr. Watson" di Jonathan Lunman.

Public Const SYSEXC_MAXIMUM_PARAMETERS = 15
'Not exactly as in API, shorter declaration, but internally the same
Type CONTEXT
  Dbls(0 To 66) As Double
  Longs(0 To 6) As Long
End Type

Type SYSEXC_RECORD
    ExceptionCode As Long
    ExceptionFlags As Long
    pExceptionRecord As Long
    ExceptionAddress As Long
    NumberParameters As Long
    ExceptionInformation(SYSEXC_MAXIMUM_PARAMETERS) As Long
End Type    
Type SYSEXC_POINTERS
    pExceptionRecord As SYSEXC_RECORD
    ContextRecord As CONTEXT
End Type

Private Declare Function SetUnhandledExceptionFilter Lib "kernel32" _
    (ByVal lpTopLevelExceptionFilter As Long) As Long
Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" _
    (Destination As Any, Source As Any, ByVal Length As Long)
Private Declare Sub CopyExceptionRecord Lib "kernel32" Alias "RtlMoveMemory" (pDest As SYSEXC_RECORD, ByVal LPSYSEXC_RECORD As Long, ByVal lngBytes As Long)


Public Property Get ErrSysHandlerWasSet() As Boolean
    ErrSysHandlerWasSet = mSysHandlerWasSet
End Property


Public Sub ErrSysHandlerSet()
    If mSysHandlerWasSet Then ErrSysHandlerRelease
    Call SetUnhandledExceptionFilter(AddressOf SysExcHandler)
    mSysHandlerWasSet = True
End Sub

Public Sub ErrSysHandlerRelease()
    ErrPreserve 'This Sub may be called from error handler, so preserve errors
    On Error Resume Next
    If mSysHandlerWasSet Then Call SetUnhandledExceptionFilter(0)
    mSysHandlerWasSet = False
    ErrRestore
End Sub

'========================== Private stuff ===========================================
Private Function SysExcHandler(ByRef ExcPtrs As SYSEXC_POINTERS) As Long
  Dim ExcRec As SYSEXC_RECORD, strExc As String
  ExcRec = ExcPtrs.pExceptionRecord
  Do Until ExcRec.pExceptionRecord = 0
    CopyExceptionRecord ExcRec, ExcRec.pExceptionRecord, Len(ExcRec)
  Loop
  strExc = GetExcAsText(ExcRec.ExceptionCode)
  Err.Raise ERR_SYSEXCEPTION, SRC_SYSHANDLER, _
    "(&H" & Hex$(ExcRec.ExceptionCode) & ") " & strExc
End Function

Private Function GetExcAsText(ByVal ExcNum As Long) As String
    Select Case ExcNum
        Case SYSEXC_ACCESS_VIOLATION:          GetExcAsText = "Access violation"
        Case SYSEXC_DATATYPE_MISALIGNMENT:     GetExcAsText = "Datatype misalignment"
        Case SYSEXC_BREAKPOINT:                GetExcAsText = "Breakpoint"
        Case SYSEXC_SINGLE_STEP:               GetExcAsText = "Single step"
        Case SYSEXC_ARRAY_BOUNDS_EXCEEDED:     GetExcAsText = "Array bounds exceeded"
        Case SYSEXC_FLT_DENORMAL_OPERAND:      GetExcAsText = "Float Denormal Operand"
        Case SYSEXC_FLT_DIVIDE_BY_ZERO:        GetExcAsText = "Divide By Zero"
        Case SYSEXC_FLT_INEXACT_RESULT:        GetExcAsText = "Floating Point Inexact Result"
        Case SYSEXC_FLT_INVALID_OPERATION:     GetExcAsText = "Invalid Operation"
        Case SYSEXC_FLT_OVERFLOW:              GetExcAsText = "Float Overflow"
        Case SYSEXC_FLT_STACK_CHECK:           GetExcAsText = "Float Stack Check"
        Case SYSEXC_FLT_UNDERFLOW:             GetExcAsText = "Float Underflow"
        Case SYSEXC_INT_DIVIDE_BY_ZERO:        GetExcAsText = "Integer Divide By Zero"
        Case SYSEXC_INT_OVERFLOW:              GetExcAsText = "Integer Overflow"
        Case SYSEXC_PRIVILEGED_INSTRUCTION:    GetExcAsText = "Privileged Instruction"
        Case SYSEXC_IN_PAGE_ERROR:             GetExcAsText = "In Page Error"
        Case SYSEXC_ILLEGAL_INSTRUCTION:       GetExcAsText = "Illegal Instruction"
        Case SYSEXC_NONCONTINUABLE_EXCEPTION:  GetExcAsText = "Non Continuable Exception"
        Case SYSEXC_STACK_OVERFLOW:            GetExcAsText = "Stack Overflow"
        Case SYSEXC_INVALID_DISPOSITION:       GetExcAsText = "Invalid Disposition"
        Case SYSEXC_GUARD_PAGE_VIOLATION:      GetExcAsText = "Guard Page Violation"
        Case SYSEXC_INVALID_HANDLE:            GetExcAsText = "Invalid Handle"
        Case SYSEXC_CONTROL_C_EXIT:            GetExcAsText = "Control-C Exit"
    End Select
End Function

Controlla la SetUnhandledExceptionFilter Funzione a MSDN per ulteriori informazioni.

Altri suggerimenti

Se questa applicazione è in esecuzione in Windows XP o successivo prova a guardare utilizzando Vectored gestione delle eccezioni. Siete in grado di scrivere un semplice insieme di DLL C ++ o utilizzare chiamate API per intrappolare le varie attività che si verificano nel API Win32.

articolo MSDN

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top