如何路线exe异常回到维生素b6程序?
-
11-09-2019 - |
题
我有一个维生素b6应用程序,这将呼叫的mencoder.exe 这一部分下将一些文件享受高品质的格式。我得到这个古怪的未经处理的异常问题,从mencoder每当我试图把这一opendivx文件。
此刻,我不清楚是否是这个编译码器是罪魁祸首。不管怎么样,我已经尝试修改命令行,甚至下载的最新版本mencoder.
所以转换工作正常和唯一的问题是,mencoder会崩溃的结束,作为视频文件不知怎的,超过100%至102%的.因此,我的问题是如何路线,这个例外的处理方式通过我的维生素b6应用程序,这样的丑陋的错误弹出会不会显示?
我甚至包含的例外捕获的编码,但它没有赶上,例外。
' 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
更新:
而如果你们是好奇什么样的应用程序是输的时候它会崩溃,这就是:
1重复的框架(s)!
Pos:83.2s2504f(99%)112.65》Trem:0min6兆A-V:0.008[571:79]] 1重复的框架(s)!
Pos:83.4s2510f(102%)112.74》Trem:0min6兆A-V:0.006[571:79] 1重复的框架(s)!
Pos:83.6s2516f(102%)112.84》Trem:0min6兆A-V:0.004[571:79] 1重复的框架(s)!
[mpeg4@0x1ac53a0]隐瞒40直流电,交流40,40MV一个错误-V:0.003[571:79]
alt文本http://img21.imageshack.us/img21/4539/exception.png
谢谢:)
解决方案
您可以尝试使用SetUnhandledExceptionFilter API来捕获异常。我以前使用过它,但只有有限的成功。 我相信这个代码最初无论是从哪里来的,在很大程度上受到影响,或者被激发,在5月99 Visual Basic程序员杂志的文章称“也不例外错误,我亲爱的华生医生”由乔纳森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
查看 SetUnhandledExceptionFilter功能在MSDN获得更多信息。
其他提示
如果这个应用程序是Windows XP下运行的或以后试试看使用量例外处理。你能写出一套简单的C++Dll或使用API呼吁陷阱的各种活动中发生的Win32API。