どのようにバックVB6アプリへのルートexeファイルの例外をしますか?
-
11-09-2019 - |
質問
私はいくつかのファイルはFLV形式に変換するためのmplayerの一部であるmencoder.exeを呼び出しますVB6のアプリを持っています。私はこの1 opendivxファイルを変換しようとするたびに、私はmencoderのからこの奇妙な未処理の例外の問題を取得しています。
は、現時点では、私はこのコーデックは、この背後に犯人であるかどうかの不明確です。私が持っているいずれかの方法は、コマンドラインを変更しようとさえmencoderのために利用可能な最新バージョンをダウンロードしました。
ので、変換が正常に動作し、唯一の問題は、ビデオファイルが何らかの形で、102%の100%を超えるようmencoderのは、最後にクラッシュするということです。したがって、私の質問は、私のルート醜いエラーのポップアップが表示されないように、この例外が私のVB6アプリによって処理されるどのように行うのですか?
私も、コードで例外キャプチャを含めましたが、それはその例外をキャッチしていない。
' 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)!
順位:83.2s 2504f(99%)のTremを112.65fps:0minの6メガバイトA-V:0.008 [571:79] 1つの重複フレーム(S)!
順位は:0minの6メガバイトのA-V:0.006 [571:79] 83.4s 2510f(102パーセント)のTremを112.74fps 1つの重複フレーム(S)!
順位は:0minの6メガバイトのA-V:0.004 [571:79] 83.6s 2516f(102パーセント)のTremを112.84fps 1つの重複フレーム(S)!
[MPEG4 @ 0x1ac53a0] 40 DCを隠し、40 AC、40 MV誤差-V:0.003 [571:79]
http://img21.imageshack.us/img21/4539/exception .PNGする
ありがとう:)
解決
あなたは、例外をキャッチするSetUnhandledExceptionFilterのAPIを使用して試みることができます。私は、しかし、限られた成功を収めて、以前にそれを使用しました。 私は、このコードは、もともとどちらかが、月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の簡単なセットを記述するかのWin32 APIで発生したトラップの様々な活動へのAPI呼び出しを使用することができます。