Question

J'ai des applications VB6 qui appelleront la mencoder.exe qui fait partie de la mplayer pour convertir des fichiers en format flv. Je reçois ce problème bizarre d'exception non gérée de mencoder chaque fois que je tente de convertir ce fichier un OpenDivX.

À l'heure actuelle, je ne suis pas clair si ce codec est est le coupable derrière tout cela. De toute façon je dois essayer de modifier la ligne de commande et même téléchargé la dernière version disponible pour mencoder.

la conversion fonctionne très bien et le seul problème est que le mencoder se bloque à la fin, que le fichier vidéo dépasse en quelque sorte 100% à 102%. ma question est donc comment puis-je acheminer cette exception à traiter par mon application VB6 de telle sorte que la fenêtre d'erreur laide ne sera pas affiché?

J'ai même inclus la capture d'exception dans le code, mais il n'est pas attraper cette exception.

    ' 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

Mises à jour:

et dans le cas où les gars vous êtes curieux de ce que l'application a été quand il fournir en sortie plantage, la voici:

1 cadre double (s)!

Pos: 83.2s 2504f (99%) 112.65fps Trem: 0min 6mb A-V: 0,008 [571: 79]] 1 cadre double (s)!

Pos: 83.4s 2510f (102%) 112.74fps Trem: 0min 6mb A-V: 0,006 [571: 79] 1 cadre double (s)!

Pos: 83.6s 2516f (102%) 112.84fps Trem: 0min 6mb A-V: 0,004 [571: 79] 1 cadre double (s)!

[mpeg4 @ 0x1ac53a0] dissimulant 40 DC, 40 AC, 40 erreurs MV A-V: 0,003 [571: 79]

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

merci:)

Était-ce utile?

La solution

Vous pouvez essayer d'utiliser l'API SetUnhandledExceptionFilter pour attraper l'exception. Je l'ai utilisé auparavant, mais seulement avec un succès limité. Je crois que ce code à l'origine soit venu, a été fortement influencée par, ou a été inspiré par un article dans le 99 mai de Visual Basic programmeurs Journal appelé « Aucune erreur d'exception, mon cher Watson » Dr. 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

Consultez la SetUnhandledExceptionFilter Fonction à MSDN pour plus d'informations.

Autres conseils

Si cette application est en cours d'exécution sous Windows XP ou d'essayer plus tard regarder en utilisant la manipulation Vectored d'exception. Vous êtes capable d'écrire un simple ensemble de DLL C ++ ou utiliser les appels API pour piéger les diverses activités qui se produisent dans l'API Win32.

MSDN article

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top