Howto Identify an Exception?

P

Pieter

Hi,

For some procedures that throws exceptions, I would like to show different
messages to the user depending on what type of exception he's getting. For
instance this one: when the file is locked, I want a messagebox to tell that
the user has to close the file first.

Is there a way to identify an exception by some kind of unique number or
something like this? I don't want to identify it on the Exception Message
because some users are using French OS, and it'sj sutn ot right in my
opinion :)

Thanks a lot in advance,

Pieter



Exemple of the exception:


Exception Source: mscorlib
Exception Type: System.IO.IOException
Exception Message: The process cannot access the file 'C:\Documents and
Settings\LBN\Desktop\Proforma.xls' because it is being used by another
process.
Exception Target Site: WinIOError

---- Stack Trace ----
System.IO.__Error.WinIOError(errorCode As Int32, maybeFullPath As String)
Ghost.exe: N 2015149
System.IO.FileStream.Init(path As String, mode As FileMode, access As
FileAccess, rights As Int32, useRights As Boolean, share As FileShare,
bufferSize As Int32, options As FileOptions, secAttrs As
SECURITY_ATTRIBUTES, msgPath As String, bFromProxy As Boolean)
Ghost.exe: N 00998
System.IO.FileStream..ctor(path As String, mode As FileMode, access As
FileAccess)
Ghost.exe: N 00057
System.Windows.Forms.SaveFileDialog.OpenFile()
Ghost.exe: N 00154
Microsoft.Reporting.WinForms.ExportDialog.PromptFileName(fileExtension As
String)
Ghost.exe: N 00369
Microsoft.Reporting.WinForms.ExportDialog.OnExportCompleteUI(result As
ProcessThreadResult, data As Object)
Ghost.exe: N 00116
 
R

rowe_newsgroups

Why not use the standard try catch blocks?

i.e.

Try
' Whatever
Catch ex as InvalidOperatationException
msgbox(" Invalid Op!")
Catch ex as FileIOException
msgbox("File IO Exception!")
Catch ex as Exception
' Grabs all the other exception (well, for the most part)
msgbox(ex.message)
End Try

Thanks,

Seth Rowe
 
I

Israel

Pieter said:
Is there a way to identify an exception by some kind of unique number or
something like this?

I may be wrong but I don't believe there's a way to do this. You
could try calling the Win32 method GetLastError() but I don't think
there's any guarantee that it wasn't reset to something else
between the file access and when you got the exception.

This is a nice concept but personally I've never found this type of
error handling that useful plus it can be time consuming and difficult
to keep up with all of the lower level error codes that may come back.
In addition it may be so far removed from your original request that
it's impossible disambiguate between multiple scenarios. What if
some virus scanner is holding on to a lock to that file and when the
user tries to open it your message tells them to close it. Then
they'll just get annoyed with your app because they don't have it
open. That later will just get them annoyed with windows in general
- which is always better.
Personally I feel that higher level processes should provide more
general type errors. For example just a "Failed to open file" with
the option to look at the details which would be "The process cannot
access the file 'C:\Documents and
Settings\LBN\Desktop\Proforma.xls' because it is being used by another
process."
 
I

Israel

rowe_newsgroups said:
Why not use the standard try catch blocks?

I thought that he was trying to distinguish between multliple
exceptions that may all be of the type IOException since there aren't
exception classes for every type of error.
 
R

Robinson

Pieter said:
Hi,

For some procedures that throws exceptions, I would like to show different
messages to the user depending on what type of exception he's getting. For
instance this one: when the file is locked, I want a messagebox to tell
that the user has to close the file first.

Is there a way to identify an exception by some kind of unique number or
something like this? I don't want to identify it on the Exception Message
because some users are using French OS, and it'sj sutn ot right in my
opinion :)

Thanks a lot in advance,

Pieter

You should handle exceptions you know about explicitly. If you expect you
might get a general error (i.e. an error you don't know about or didn't
think about), then you catch it with a standard "catch all". It is often
useful to put the catch all exception handler as a top level handler in your
main method, especially if you intend to terminate the program when it
happens:

Now as for your French users, in general users won't have a clue what the
exception message returned means, no clue whatsoever, even the English
speaking ones (most of them actually) especially in the context of your
running program, so there is no need to provide translations of those
messages at all. What you DO need to do, is to provide some kind of message
box/logging facility so the user can at least copy the message to the
clip-board to send to your support.

In the general case, my software operates with different error levels, the
highest is "Exception" (SystemFatal), given that if I don't know what the
error is, I have no confidence that the software can continue without
borking up something else. For example:

Public Enum ErrorClassEnum

OK ' Success
Fail 'In a multiple iteration operation, fail the iteration, not the
whole operation
Fatal 'Terminate the entire operation
SystemFatal 'Terminate the program
Cancel 'Terminate the entire operation, don't display an error message

End Enum

the "Ex As Exception" is SystemFatal for me, whereas the SqlException might
be SystemFatal, Fatal or Fail, depending on what the error number is. Many
SystemFatal exceptions are caused by bad programming rather than real system
errors. For example, divison by zero, null-reference exception, etc. You
can code defensively to avoid many of these ever happening.
 
S

ssamuel

Pieter,

The trick is to put several individual try/catch blocks around small
blocks of code. If you need that finely-grained control, a "block" may
be a single method call. RTFM and decide what you need to catch.

For instance, on the StreamReader(string) constructor, there are 5
possible exceptions that can be thrown. Based on context, each one can
mean only one thing. Do something like:

// Get string strFilename from user.
StreamReader myStream;
try
{
myStream = new StreamReader(strFilename);
}
catch (ArgumentException)
{
// The filename string was empty.
}
catch (ArgumentNullException)
{
// The filename string was null.
}
catch (FileNotFoundException)
{
// At this point, we're sure that the filename string was valid, but
there's
// no valid file at the location it points to on the filesystem.
}
catch (DirectoryNotFoundException)
{
// At this point, we're sure that the filename string was valid, but
part
// of the path that it refers to is invalid.
}
catch (IOException)
{
// At this point, we know that the format of the filename is
incorrect.
}

Similarly, just about every operation involving any I/O has a similar
canonical exception list. See the documentation and figure out exactly
what to catch and what it means for the particular functions you need.

I believe it's bad coding style to *need* to catch all of those
exceptions in most cases. A much better way to do this is to
pre-validate (contract check) every variable. For instance, the
following code:

if (strFilename == null || strFilename == String.Empty)
// Break out: the filename is invalid

will take care of the first two exceptions. File.Exists() will tell you
if the file exists or not and save you catching the other three
exceptions. No exceptions are thrown -- throwing an exception is a
highly costly process -- and you get the same information. It also has
the added benefit of saving the exceptions for real exception cases.
For instance, if the user specifies a file, then between when you
capture the filename and when you try to do something with the file,
they unplug the USB device that the file is on, that's a real
exception. It's probably one you can't handle at the level of this
method, so it should get bubbled up to the main thread and handled
there, probably by telling the user, "you've done something I didn't
expect and can't correct."


Stephan
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top