How to use structured exception handling in Visual C++ .NET or in Visual C++ 2005 (816155)



The information in this article applies to:

  • Microsoft Visual C++ 2005 Express Edition
  • Microsoft Visual C++ .NET (2003)
  • Microsoft Visual C++ .NET (2002)

SUMMARY

This article describes how to use structured exception handling in Microsoft Visual C++ .NET or in Microsoft Visual C++ 2005.

back to the top

Requirements

The following list outlines the recommended hardware, software, network infrastructure, and service packs that you need:
  • Visual C++ .NET or Visual C++ 2005
This article assumes that you are familiar with the following topics:
  • Visual C++ .NET or Visual C++ 2005
  • Microsoft Visual Studio .NET or Microsoft Visual Studio 2005
back to the top

Structured Exception Handling

In Visual C++ .NET or in Visual C++ 2005, you can use structured exception handling for a powerful and a more readable way to handle errors. By using structured exception handling, you can nest error handlers inside other error handlers that are in the same procedure. Structured exception handling uses a block syntax that is similar to the If...Else...End If statement. Therefore, Visual C++ .NET or Visual C++ 2005 code is more readable and easier to maintain. You can handle exceptions in Visual C++ .NET or in Visual C++ 2005 by using a combination of the following exception handling statements:
  • try
  • catch
  • __finally
  • throw
The basic syntax of structured error handling is as follows:
try
{
  // Code that is expected to raise an exception.
}
catch(Exception *ex)
{
  // Code that can handle an error.
}
__finally
{
  // Code to do any final cleanup.
}
You can include any valid Visual C++ code in the try block, or you can include another try block or another hierarchy of try blocks. When an exception occurs at any point, the common language runtime looks for the nearest try block that encloses this code and does not run any additional lines of code. The control is then passed to a matching catch block, if one exists, and to the associated __finally block. You can also specify multiple catch statements so that each catch block handles a specific error.

back to the top

Catch an Exception

  1. Start Visual Studio .NET or Visual Studio 2005.
  2. On the File menu, point to New, and then click Project.
  3. In Visual Studio .NET 2002, click Visual C++ Projects under Project Types, and then click Managed C++ Application under Templates.

    In Visual Studio .NET 2003, click Visual C++ Projects under Project Types, and then click Console Application (.NET) under Templates.

    Note In Visual Studio 2005, click Visual C++ under Project Types, and then click Console Application under Templates.
  4. In the Name text box, type MyConsoleApp.
  5. In the Location text box, type C:\, and then click OK.
  6. In Solution Explorer, double-click MyConsoleApp.cpp to open the Code window. Replace the existing code with the following code in the main() function:
    	int a = 0;
    	int b = 10;
    	int c = 0;
    	
    	try 
    	{
    		a = b / c;
    	}
    	catch (Exception *ex)
    	{
    		Console::WriteLine(S"A run-time error occurred.");
    		Console::WriteLine(ex->Message);
    	}
    	__finally 
    	{
    		Console::ReadLine();
    	}
    	return 0;
  7. On the Debug menu, click Start to run the application. The code tries to divide the number by 0. This operation is not valid and it causes a divide-by-zero error. However, the catch block catches this error, and you receive the following error message in the Console window:
    A run-time error occurred.
    Attempted to divide by zero
  8. Close the Console window.
back to the top

Catch Multiple Exceptions

This section describes how to use multiple catch statements to handle different errors.
  1. Open the console application project that you created in the Catch an Exception section of this article.
  2. Replace the existing code in the main() function with the following code:
    	try
    	{
    		//will throw an exception if something goes wrong...
    		FileStream *fs = File::Open(S"c:\\FileNotFound.txt", FileMode::Open);
    	}
    	
    	catch (FileNotFoundException *fe)
    	{
    		//give information specific to this exception...
    		Console::WriteLine(S"Could not find the file, in the specified directory.");
    		Console::WriteLine(S"Exception : {0}",fe->Message);
    	}
    	
    	catch (Exception *ex)
    	{
    		//all OTHER scenarios...
    		Console::WriteLine(S"exception ... {0}",ex->Message);
    	}
    
    	__finally
    	{
    		Console::ReadLine();
    	}
    	return 0;
    This code includes two catch blocks:
    • One catch block that catches the FileNotFoundException exception.
    • One catch block that catches all other exceptions.
  3. Use the using directive on the System::IO namespace so that you do not have to qualify declarations from this namespaces later in your code. You must use the following statement to perform file operations before any other declarations:
    using namespace System::IO;
    Note The IO namespace contains types that permit synchronous and asynchronous reading and writing on data streams and files.
  4. On the Debug menu, click Start to run the application.
  5. Close the Console window.
  6. Because you cannot always anticipate every error that may occur, you can add a catch block for all exceptions that you cannot anticipate. For example, add the following code before the __finally statement to catch any errors that you cannot anticipate and to display the appropriate error message:
    catch (Exception *ex)
    			{
    				Console::WriteLine(S"exception ... {0}",ex->Message);
    			}
  7. On the File menu, click Close Solution.
back to the top

Throw an Exception

Structured exception handling uses the catch statement to catch an exception. With structured exception handling, you can also throw an exception. For example, you may find it useful to throw an exception when you perform data validation inside a Property Set function, because you may want to throw an error if a business rule is violated.
  1. Start Visual Studio .NET or Visual Studio 2005.
  2. On the File menu, point to New, and then click Project.
  3. In Visual Studio .NET 2002, click Visual C++ Projects under Project Types, and then click Managed C++ Console Application under Templates.

    In Visual Studio .NET 2003, click Visual C++ Projects under Project Types, and then click Console Application (.NET) under Templates.

    In Visual Studio 2005, click Visual C++ under Project Types, and then click Console Application under Templates.
  4. In the Name text box, type MyNewConsoleApp.
  5. In the Location textbox, type C:\, and then click OK.
  6. On the View menu, click Class View. Right-click MyNewConsoleApp, point to Add, and then click Add Class.
  7. Under Templates in the Add Class dialog box, click Generic C++ Class, and then click Open.

    Note In Visual Studio 2005, click Add.
  8. In Generic C++ Class Wizard, type clsPerson, and then click Finish.
    The clsPerson class appears as follows:
    #pragma once
    
    class clsPerson
    {
    public:
    	clsPerson(void);
    	~clsPerson(void);
    };
    To make the clsPerson class as the managed C++ class, add the __gc keyword in front of the clsPerson class. The modified code is as follows:
    #pragma once
    
    __gc class clsPerson
    {
    public:
    	clsPerson(void);
    	~clsPerson(void);
    };
  9. Add the following code in the clsPerson class:
    private:
    	int mintAge;
    
    public:
    	__property int get_Age(void)
    	{
    		return mintAge;
    	}
    	__property void clsPerson::set_Age(int value)
    	{
    		if(value > 0)
    			mintAge = value;
    		else
    			throw new System::ArgumentException(S"Age cannot be negative.");
    	}
    This code creates an Age property. Because a person cannot have a negative age, an error is raised if the user of the class tries to set the Age property to a number that is less than 0.
  10. In Solution Explorer, double-click MyNewConsoleApp.cpp to open the Code window, and then add the following declaration:
    #include "clsPerson.h"
  11. In the main() function of MyNewConsoleApp.cpp, replace the existing code with the following code:
    	clsPerson *p1 = new clsPerson();
    	clsPerson *p2 = new clsPerson();
    
    	try 
    	{
    		p1->Age = 60;
    		Console::WriteLine(S"Age of Person1 = {0}",p1->Age.ToString());
    		p2->Age = -1;
    		Console::WriteLine(S"Age of Person2 = {0}",p2->Age.ToString());
    	}
    	catch (Exception *e)
    	{
    		Console::WriteLine(e->Message);
    	}
    	__finally
    	{
    		Console::ReadLine();
    	}
    	return 0;
  12. On the Debug menu, click Start to run the application. You receive the following error message in the Console window:
    Age of Person1 = 60
    Age cannot be negative.
  13. Close the Console window.
back to the top

Complete Code Listing

Catch an Exception

#include <tchar.h>

#using <mscorlib.dll>

using namespace System;

int main()
{
	int a = 0;
	int b = 10;
	int c = 0;
	
	try 
	{
		a = b / c;
	}
	catch (Exception *ex)
	{
		Console::WriteLine(S"A run-time error occurred.");
	}
	__finally 
	{
		Console::ReadLine();
	}
	return 0;
}
Note You must add the common language runtime support compiler option (/clr:oldSyntax) in Visual C++ 2005 to successfully compile the previous code sample. To add the common language runtime support compiler option in Visual C++ 2005, follow these steps:
  1. Click Project, and then click <ProjectName> Properties.

    Note <ProjectName> is a placeholder for the name of the project.
  2. Expand Configuration Properties, and then click General.
  3. Click to select Common Language Runtime Support, Old Syntax (/clr:oldSyntax) in the Common Language Runtime support project setting in the right pane, click Apply, and then click OK.
For more information about the common language runtime support compiler option, visit the following Microsoft Web site:

/clr (Common Language Runtime Compilation)
http://msdn2.microsoft.com/en-us/library/k8d11d4s.aspx

Catch Multiple Exceptions

#include <tchar.h>

#using <mscorlib.dll>

using namespace System;
using namespace System::IO;

int _tmain()
{
	try
	{
		//will throw an exception if something goes wrong...
		FileStream *fs = File::Open(S"c:\\a1.txt", FileMode::Open);
	}
	
	catch (FileNotFoundException *fe)
	{
		//give information specific to this exception...
		Console::WriteLine(S"Could not find the file, in the specified directory.");
		Console::WriteLine(S"Exception : {0}",fe->Message);
	}
	
	catch (Exception *ex)
	{
		//all OTHER scenarios...
		Console::WriteLine(S"exception ... {0}",ex->Message);
	}

	__finally
	{
		Console::ReadLine();
	}
	return 0;
}

Throw an Exception

#include <tchar.h>

#using <mscorlib.dll>

using namespace System;


#pragma once

__gc class clsPerson
{
	public:
	clsPerson(void)
	{
	}
	~clsPerson(void)
	{
	}
private:
	int mintAge;

public:
	__property int get_Age(void)
	{
		return mintAge;
	}
	__property void clsPerson::set_Age(int value)
	{
		if(value > 0)
			mintAge = value;
		else
			throw new System::ArgumentException(S"Age cannot be negative.");
	}
};


int _tmain()
{
	clsPerson *p1 = new clsPerson();
	clsPerson *p2 = new clsPerson();

	try 
	{
		p1->Age = 60;
		Console::WriteLine(S"Age of Person1 = {0}",p1->Age.ToString());
		p2->Age = -1;
		Console::WriteLine(S"Age of Person2 = {0}",p2->Age.ToString());
	}
	catch (Exception *e)
	{
		Console::WriteLine(e->Message);
	}
	__finally 
	{
		Console::ReadLine();
	}
	return 0;	
}
back to the top

REFERENCES

For more information about exception management application blocks for .NET, visit the following Microsoft Developer Network (MSDN) Web site:For more information about exception handling with Managed Extensions for C++, visit the following Microsoft Developer Network (MSDN) Web site:
For more information about how to catch an exception, visit the following MSDN Web site:For more information about how to throw an exception, visit the following MSDN Web site:back to the top

Modification Type:MajorLast Reviewed:1/5/2006
Keywords:kbProgramming kbExceptHandling kbHOWTOmaster KB816155 kbAudDeveloper kbAudITPRO