I have a serialisable class called DataSet which has a static method Load(string filename, string password)
which returns the deserialised DataSet.
Here it is:
public static DataSet Load(string filename, string password)
{
if (!File.Exists(filename))
throw new FileNotFoundException("File not found.", filename);
DataSet ds;
ICryptoTransform ct = Encryption.getDecryptor(password, salt, iv);
using (FileStream fs = new FileStream(filename, FileMode.Open, FileAccess.Read))
{
using (CryptoStream cs = new CryptoStream(fs, ct, CryptoStreamMode.Read))
{
using (GZipStream zs = new GZipStream(cs, CompressionMode.Decompress))
{
try
{
ds = (DataSet)new BinaryFormatter().Deserialize(zs);
return ds;
}
catch
{
throw new ApplicationException("This password cannot be used to decrypt this file. Either the password is incorrect or the file is corrupt");
}
finally
{
zs.Close();
}
}
}
}
}
And I'm calling it like this:
try
{
dataSet = DataSet.Load(ofd.FileName, ep.Password);
}
catch (ApplicationException ae)
{
MessageBox.Show("Error:\r\n" + ae.Message, "Authorisation Error", MessageBoxButtons.RetryCancel, MessageBoxIcon.Error);
}
With the correct password, it works fine. I'm testing it with the incorrect password. The expected result is for a MessageBox to pop up saying "This password cannot be used to decrypt this file [...]". Instead, what happens is I get an uncaught exception window.
If I'm debugging in VS, I can see that an uncaught CryptographicException occurred. I originally had a try/catch with 2 catches, one for CryptographicException and one for SerializationException. That didn't work. I replaced it to catch Exception. Finally, I have a catch all.
I don't know why, but for some reason it cannot seem to catch this? I'm sure the answer is very obvious but I just can't see it.
I know some exceptions are uncatchable such as StackoverflowException. I suspect CryptographicException is not uncatchable.
The reason that your ApplicationException
is not "taking precedence" is because the CryptographicException
is being thrown from outside your try/catch
block.
In other words, Deserialize
is not the only API that can throw a CryptographicException
. You simply need to enlarge your try/catch/finally
block to encompass all API calls that might throw an exception. After you have done this, ApplicationException
will be the only possible exception that Load
can throw and your code should work as expected.