|
-
Apr 2nd, 2011, 01:04 PM
#1
Thread Starter
Fanatic Member
[RESOLVED] Exception Problems.
Hi all,
I'm Creating a wrapper dll for my favorite Windows API functions. Normally when windows API calls fail, Nothing happens and you don't know why and this frustrates me. Although you can use their return value to determine If it was successful.
My code (one example)
vb.net Code:
Public Function SetParent(ByVal hWndChild As IntPtr, ByVal hWndNewParent As IntPtr) As IntPtr Dim result As IntPtr = Declarations.SetParent(hWndChild, hWndNewParent) If result = IntPtr.Zero Then Dim ex As New System.ComponentModel.Win32Exception(Runtime.InteropServices.Marshal.GetLastWin32Error) throw ex End If End Function
My problem is that when I create a new exception to be thrown I can't set the stack trace or other necessary information. I need to set this because when I just throw the exception the debugger will go to the line that threw the exception and Not the actual call.
Any ideas ?
EDIT: It seems like the only way is to create a custom exception. I don't want to do that since I like the Win32 exception.
Last edited by BlindSniper; Apr 2nd, 2011 at 01:10 PM.
-
Apr 2nd, 2011, 02:44 PM
#2
Re: Exception Problems.
Add a
Code:
<DebuggerStepThrough()> _
attribute on the line before your function.
-
Apr 2nd, 2011, 02:56 PM
#3
Thread Starter
Fanatic Member
Re: Exception Problems.
That is quite cool Thanks !
-
Apr 2nd, 2011, 05:45 PM
#4
Re: [RESOLVED] Exception Problems.
 Originally Posted by BlindSniper
Hi all,
Normally when windows API calls fail, Nothing happens and you don't know why and this frustrates me. Although you can use their return value to determine If it was successful.
For a fully trusted application you can get both an error code and description for a failure of an API call shown below.
Code:
Imports System.Runtime.InteropServices
Imports System.ComponentModel
Public Class Form1
Private Sub cmdTest_Click() Handles cmdTest.Click
Console.WriteLine("Calling Win32 MessageBox without error...")
Win32.MessageBox(New IntPtr(0), "Press OK...", "Press OK Dialog", 0)
Dim ErrorCode As Integer = Marshal.GetLastWin32Error()
If ErrorCode = 0 Then
Console.WriteLine("1. Worked just fine")
Else
Dim ErrorMsg As New Win32Exception(ErrorCode)
Console.WriteLine("1. The last Win32 Error was: {0} Description [{1}]", _
ErrorCode, ErrorMsg.Message)
End If
' Call the MessageBox with an invalid window handle to produce a Win32 error.
Win32.MessageBox(New IntPtr(123132), "Press OK...", "Press OK Dialog", 0)
ErrorCode = Marshal.GetLastWin32Error()
If ErrorCode = 0 Then
Console.WriteLine("2. Worked just fine")
Else
Dim ErrorMsg As New Win32Exception(ErrorCode)
Console.WriteLine("2. The last Win32 Error was: {0} Description [{1}]", _
ErrorCode, ErrorMsg.Message)
End If
End Sub
End Class
Code:
Imports System.Runtime.InteropServices
Module Win32
' Use DllImportAttribute to inport the Win32 MessageBox
' function. Set the SetLastError flag to true to allow
' the function to set the Win32 error.
<DllImportAttribute("user32.dll", _
SetLastError:=True, _
CharSet:=CharSet.Unicode)> _
Function MessageBox( _
ByVal hwnd As IntPtr, _
ByVal text As String, _
ByVal caption As String, _
ByVal type As UInt32) As Integer
End Function
<DllImport("Kernel32.dll", _
EntryPoint:="FormatMessageW", _
SetLastError:=True, _
CharSet:=CharSet.Unicode, _
CallingConvention:=CallingConvention.StdCall)> _
Public Function FormatMessage( _
ByVal dwFlags As Integer, _
ByRef lpSource As IntPtr, _
ByVal dwMessageId As Integer, _
ByVal dwLanguageId As Integer, _
ByRef lpBuffer As String, _
ByVal nSize As Integer, _
ByRef Arguments As IntPtr) As Integer
End Function
End Module
Output
Code:
Calling Win32 MessageBox without error...
1. Worked just fine
2. The last Win32 Error was: 1400 Description [Invalid window handle]
-
Apr 2nd, 2011, 05:51 PM
#5
Fanatic Member
Re: [RESOLVED] Exception Problems.
Since it fits here any ways, same as kevin, a few functions to shorten it all. Import interopservices btw.
Code:
Public Shared Function HasError() As Boolean
Return Marshal.GetLastWin32Error() <> 0
End Function
Public Shared Function LastError() As Exception
Return New System.ComponentModel.Win32Exception(Marshal.GetLastWin32Error())
End Function
<DebuggerStepThrough()> _
Public Shared Sub HandleError()
If HasError() Then Throw LastError
End Sub
Public Sub ThrowError(Optional ByVal location As String = "")
Dim ex As New System.ComponentModel.Win32Exception(Runtime.InteropServices.Marshal.GetLastWin32Error())
If ex.NativeErrorCode <> 0 Then MessageBox.Show(ex.Message, "Error at " & location, MessageBoxButtons.OK, MessageBoxIcon.Error)
End Sub
Public Function GetLastError() As String
Return New System.ComponentModel.Win32Exception(Runtime.InteropServices.Marshal.GetLastWin32Error()).Message
End Function
Code:
'Error in an API right here
ThrowError("Sending a message to my form.")
MsgBox(GetLastError())
HandleError()
If HasError Then Throw LastError()
Last edited by bergerkiller; Apr 2nd, 2011 at 05:58 PM.
-
Apr 2nd, 2011, 05:55 PM
#6
Re: [RESOLVED] Exception Problems.
 Originally Posted by bergerkiller
Since it fits here any ways, same as kevin, a few functions to shorten it all. Import interopservices btw.
Code:
Public Shared Function HasError() As Boolean
Return Marshal.GetLastWin32Error() <> 0
End Function
Public Shared Function LastError() As Exception
Get
Return New System.ComponentModel.Win32Exception(Marshal.GetLastWin32Error())
End If
End Get
End Function
Public Sub ThrowError(Optional ByVal location As String = "")
Dim ex As New System.ComponentModel.Win32Exception(Runtime.InteropServices.Marshal.GetLastWin32Error())
If ex.NativeErrorCode <> 0 Then MessageBox.Show(ex.Message, "Error at " & location, MessageBoxButtons.OK, MessageBoxIcon.Error)
End Sub
Public Function GetLastError() As String
Return New System.ComponentModel.Win32Exception(Runtime.InteropServices.Marshal.GetLastWin32Error()).Message
End Function
I've corrected the errors in your syntax:
Code:
Public Shared Function HasError() As Boolean
Return Marshal.GetLastWin32Error() <> 0
End Function
Public Shared ReadOnly Property LastError() As ComponentModel.Win32Exception
Get
Return New ComponentModel.Win32Exception(Marshal.GetLastWin32Error())
End Get
End Function
Public Sub ThrowError(Optional ByVal location As String = "")
Dim ex As ComponentModel.Win32Exception = LastError
If ex.NativeErrorCode <> 0 Then MessageBox.Show(ex.Message, "Error at " & location, MessageBoxButtons.OK, MessageBoxIcon.Error)
End Sub
Public Function GetLastError() As String
Return LastError.Message
End Function
EDIT: I see you edited your post.
Last edited by minitech; Apr 2nd, 2011 at 06:05 PM.
-
Apr 2nd, 2011, 06:04 PM
#7
Fanatic Member
Re: [RESOLVED] Exception Problems.
Yep sorry, noticed the leftovers from the property->function change just as you did. 
Ow and the last two functions came from a separate class, thus the duplicate exception creation code.
Made it all even shorter, all you have to do is call "HandleError" and it will bring you to where it is called if there is an error, and display the exception in the debugger:
Code:
'Error handling
Private Shared LastError As Exception
<DebuggerStepThrough()> _
Public Shared Sub HandleError()
If LastError IsNot Nothing Then
Throw LastError
ElseIf Marshal.GetLastWin32Error() <> 0 Then
Throw New System.ComponentModel.Win32Exception(Marshal.GetLastWin32Error())
End If
End Sub
The LastError member allows you to specify a custom error in case the LastWin32Error is not set.
Last edited by bergerkiller; Apr 2nd, 2011 at 06:11 PM.
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|