Pergunta

eu tenho um aplicativos VB6 que irá chamar o mencoder.exe que faz parte do mplayer para converter alguns arquivos em formato flv. Estou recebendo este problema excepção não estranho de mencoder Sempre que eu tento converter este arquivo de um OpenDivX.

No momento, eu sou claro sobre se é este codec é o culpado por trás disso. De qualquer forma eu tenho tentar modificar a linha de comando e até mesmo baixei a última versão disponível para mencoder.

para a conversão funciona bem eo único problema é que o mencoder irá falhar no final, como o arquivo de vídeo de alguma forma superior a 100% a 102%. assim, a minha pergunta é como faço rota essa exceção para serem manipulados pelo meu aplicativo VB6 para que o pop-up de erro feio não será exibido?

i incluídos ainda a captura de exceção no código, mas não é pegar essa exceção.

    ' 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

Atualizações:

e no caso de vocês estão curiosos que o pedido foi a saída quando ele falhar, aqui está:

1 duplicado quadro (s)!

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

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

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

[MPEG4 @ 0x1ac53a0] ocultando 40 DC, AC 40, 40 MV erros A-V: 0,003 [571: 79]

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

graças:)

Foi útil?

Solução

Você pode tentar usar a API SetUnhandledExceptionFilter para capturar a exceção. Eu usei-o anteriormente, mas apenas com sucesso limitado. Eu acredito que este código originalmente tanto veio, foi fortemente influenciada por, ou foi inspirado por, um artigo na Maio 99 Visual Basic programadores Journal chamado "Não há erros de exceção, meu caro Dr. Watson" por 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

Confira o SetUnhandledExceptionFilter Função em MSDN para mais informações.

Outras dicas

Se este aplicativo é executado no Windows XP ou mais tarde tentar olhar em usar Vectored manipulação de exceção. Você é capaz de escrever um simples conjunto de C ++ DLLs ou utilização chamadas de API para prender várias atividades que ocorrem na API Win32.

MSDN artigo

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top