diff --git a/pykd/context.cpp b/pykd/context.cpp
index 08a77d1..2c2cfab 100644
--- a/pykd/context.cpp
+++ b/pykd/context.cpp
@@ -25,7 +25,7 @@ void Registers::getI386Context(
 
     HRESULT hres = advanced->GetThreadContext(&Context, sizeof(Context));
     if (S_OK != hres)
-        throw Exception( pykd::buildExceptDesc("IDebugAdvanced2::GetThreadContext", hres) );
+        throw Exception( "IDebugAdvanced2::GetThreadContext", hres );
 
     m_regValues[CV_REG_DR0] = Context.Dr0;
     m_regValues[CV_REG_DR1] = Context.Dr1;
@@ -73,7 +73,7 @@ void Registers::getAmd64Context(
 
     HRESULT hres = advanced->GetThreadContext(&Context, sizeof(Context));
     if (S_OK != hres)
-        throw Exception( pykd::buildExceptDesc("IDebugAdvanced2::GetThreadContext", hres) );
+        throw Exception( "IDebugAdvanced2::GetThreadContext", hres);
 
     m_regValues[CV_AMD64_MXCSR] = Context.MxCsr;
 
@@ -122,7 +122,7 @@ Registers::Registers(
 {
     HRESULT hres = control->GetExecutingProcessorType(&m_processorType);
     if (S_OK != hres)
-        throw Exception( pykd::buildExceptDesc("IDebugControl::GetExecutingProcessorType", hres) );
+        throw Exception( "IDebugControl::GetExecutingProcessorType", hres );
 
     switch (m_processorType)
     {
diff --git a/pykd/dbgclient.h b/pykd/dbgclient.h
index ab034ed..52eec42 100644
--- a/pykd/dbgclient.h
+++ b/pykd/dbgclient.h
@@ -42,7 +42,7 @@ private:
         T retValue;
         HRESULT hres = (m_control->*method)(&retValue);
         if (S_OK != hres)
-            throw DbgException( buildExceptDesc(methodName, hres) );
+            throw DbgException( methodName, hres);
         return retValue;
     }
     #define getDbgControl(method)  \
diff --git a/pykd/dbgexcept.cpp b/pykd/dbgexcept.cpp
index f2494a6..2997b7d 100644
--- a/pykd/dbgexcept.cpp
+++ b/pykd/dbgexcept.cpp
@@ -1,87 +1,16 @@
 #include "stdafx.h"
 #include "dbgexcept.h"
+#include "diawrapper.h"
 
 namespace pykd {
 
-////////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////////
 
-PyObject *DbgException::baseExceptTypeObject = NULL;
-PyObject *MemoryException::memoryExceptionTypeObject = NULL;
-PyObject *WaitEventException::waitEventExceptTypeObject = NULL;
+PyObject   *ExceptionTranslator<DbgException>::exceptTypeObject = NULL;
+PyObject   *ExceptionTranslator<MemoryException>::exceptTypeObject = NULL;
+PyObject   *ExceptionTranslator<WaitEventException>::exceptTypeObject = NULL;
+PyObject   *ExceptionTranslator<pyDia::Exception>::exceptTypeObject = NULL;
 
-/////////////////////////////////////////////////////////////////////////////////
-
-void DbgException::exceptionTranslate( const DbgException &e )
-{
-    python::object pyExcept(e);
-
-    PyErr_SetObject( baseExceptTypeObject, pyExcept.ptr() );
-}
-
-/////////////////////////////////////////////////////////////////////////////////
-
-void MemoryException::exceptionTranslate( const MemoryException &e )
-{
-    python::object pyExcept(e);
-
-    PyErr_SetObject( memoryExceptionTypeObject, pyExcept.ptr() );
-}
-
-/////////////////////////////////////////////////////////////////////////////////
-
-std::string buildExceptDesc(PCSTR routineName, HRESULT hres)
-{
-    std::stringstream sstream;
-    sstream << "Call " << routineName << " failed\n";
-    sstream << "HRESULT 0x" << std::hex << hres;
-    return sstream.str();
-}
-
-/////////////////////////////////////////////////////////////////////////////////
-
-void WaitEventException::exceptionTranslate( const WaitEventException &e )
-{
-    python::object pyExcept(e);
-
-    PyErr_SetObject( waitEventExceptTypeObject, pyExcept.ptr() );
-}
-
-
-/////////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////////
 
 }; // end namespace pykd
-
-
-
-
-
-//PyObject    *eventExceptionType = NULL;
-//PyObject    *typeExceptionType = NULL;
-//PyObject    *memoryExceptionType = NULL;
-//
-//void WaitEventException::exceptionTranslate( const WaitEventException &e )
-//{
-//    boost::python::object                   pyExcept(e);
-//
-//    PyErr_SetObject( eventExceptionType, pyExcept.ptr());
-//}
-//
-///////////////////////////////////////////////////////////////////////////////////
-//
-//void TypeException::exceptionTranslate( const TypeException &e )
-//{
-//    boost::python::object                   pyExcept(e);
-//   
-//    PyErr_SetObject( typeExceptionType, pyExcept.ptr());    
-//}
-//
-///////////////////////////////////////////////////////////////////////////////////
-//
-//void MemoryException::translate( const MemoryException &e )
-//{
-//    boost::python::object                   pyExcept(e);
-//
-//    PyErr_SetObject( memoryExceptionType, pyExcept.ptr());    
-//}
-//
-///////////////////////////////////////////////////////////////////////////////////
\ No newline at end of file
diff --git a/pykd/dbgexcept.h b/pykd/dbgexcept.h
index 078394d..a81b12a 100644
--- a/pykd/dbgexcept.h
+++ b/pykd/dbgexcept.h
@@ -5,30 +5,51 @@
 
 namespace pykd {
 
+/////////////////////////////////////////////////////////////////////////////////
+
+template<typename TExcept>
+class ExceptionTranslator {
+
+public:
+
+    static
+    void
+    exceptionTranslate(const TExcept &e ) {
+        python::object pyExcept(e);
+        PyErr_SetObject( exceptTypeObject, pyExcept.ptr() );
+    }
+
+    static void setTypeObject(PyObject *p) {
+        exceptTypeObject = p;
+        python::register_exception_translator<TExcept>( &exceptionTranslate );
+    }
+
+private:
+
+    static PyObject *exceptTypeObject;
+
+};
 
 /////////////////////////////////////////////////////////////////////////////////
 
-class PyException 
+class PyException : public std::exception
 {
 public:
 
     PyException( PyObject*  pyObj, const std::string &desc ) :
-        m_typeObj( pyObj ),
-        m_desc( desc )
+        std::exception( desc.c_str() ),
+        m_typeObj( pyObj )
         {}    
 
     static
     void
     exceptionTranslate(const PyException &e ) {
-        PyErr_SetString( e.m_typeObj, e.m_desc.c_str() );
+        PyErr_SetString( e.m_typeObj, e.what() );
     }
 
 private:
 
     PyObject*       m_typeObj;
-
-    std::string     m_desc;
-
 };
 
 /////////////////////////////////////////////////////////////////////////////////
@@ -39,29 +60,40 @@ public:
 
     DbgException( const std::string  &desc ) :
         std::exception( desc.c_str() )
-        {}
+        {}    
+
+    DbgException( const std::string  &methodName, HRESULT hres ) :
+        std::exception( buildHresultDesc( methodName, hres ).c_str() )
+        {}    
 
     const char* getDesc() const {
         return what();
     }
 
-    static
-    void
-    exceptionTranslate(const DbgException &e );
-
-    static void setTypeObject(PyObject *p) {
-        baseExceptTypeObject = p;
-    }
-
-    std::string print() {
-         return what();
-    }
-
 private:
-    static PyObject *baseExceptTypeObject;
+
+    std::string buildHresultDesc( const std::string  &methodName, HRESULT hres ) 
+    {
+        std::stringstream sstream;
+        sstream << "Call " << methodName << " failed\n";
+        sstream << "HRESULT 0x" << std::hex << hres;
+        return sstream.str();
+    }
+
 };
 
-///////////////////////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////////////////////
+
+class WaitEventException : public DbgException
+{
+public:
+
+    WaitEventException() 
+       : DbgException( "None of the targets could generate events" )
+        {}
+};
+
+/////////////////////////////////////////////////////////////////////////////////
 
 class MemoryException : public DbgException
 {
@@ -69,16 +101,8 @@ public:
 
     MemoryException( ULONG64 targetAddr, bool phyAddr = false ) :
         m_targetAddress( targetAddr ),
-        DbgException( MemoryException::DescMaker( targetAddr, phyAddr ).desc() )
+        DbgException( buildDesc( targetAddr, phyAddr ) )
         {}    
-       
-    static
-    void
-    exceptionTranslate( const MemoryException &e );
-
-    static void setTypeObject(PyObject *p) {
-        memoryExceptionTypeObject = p;
-    }
     
     ULONG64
     getAddress() const {
@@ -89,175 +113,19 @@ private:
         
     ULONG64             m_targetAddress;
 
-    static PyObject     *memoryExceptionTypeObject;
-    
-    class DescMaker {
-    public:
-        DescMaker( ULONG64 addr, bool phyAddr )
-        {
-            std::stringstream   sstr;
-            if ( phyAddr )
-                sstr << "Memory exception at 0x" << std::hex << addr << " target physical address";
-            else
-                sstr << "Memory exception at 0x" << std::hex << addr << " target virtual address";                            
-            m_desc = sstr.str();
-        }   
-        
-        const std::string&
-        desc() const {
-            return m_desc;
-        }
-        
-    private:
-        std::string     m_desc;
-    };
-};
-
-std::string buildExceptDesc(PCSTR routineName, HRESULT hres);
-
-
-///////////////////////////////////////////////////////////////////////////////////
-
-class WaitEventException : public DbgException
-{
-public:
-    WaitEventException()
-        : DbgException( "None of the targets could generate events" )
+    std::string buildDesc( ULONG64 addr, bool phyAddr )
     {
-    }
-
-    static void exceptionTranslate(const WaitEventException &e);
-
-    static void setTypeObject(PyObject *p) {
-        waitEventExceptTypeObject = p;
-    }
-private:
-    static PyObject *waitEventExceptTypeObject;
+        std::stringstream   sstr;
+        if ( phyAddr )
+            sstr << "Memory exception at 0x" << std::hex << addr << " target physical address";
+        else
+            sstr << "Memory exception at 0x" << std::hex << addr << " target virtual address";                            
+       
+        return sstr.str();
+    }   
 };
 
-///////////////////////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////////////////////
 
 }; // namespace pykd
 
-///////////////////////////////////////////////////////////////////////////////////
-
-
-
-
-
-
-
-
-
-
-
-
-
-//
-//class WaitEventException : public DbgException
-//{
-//public:
-//    WaitEventException()
-//        : DbgException( "none of the targets could generate events" )
-//    {
-//    }
-//
-//    static void exceptionTranslate(const WaitEventException &e);
-//};
-//
-///////////////////////////////////////////////////////////////////////////////////
-//
-//class TypeException : public DbgException
-//{
-//public:
-//
-//    TypeException() :
-//        DbgException( "type operation invalid" )
-//        {}
-//
-//    TypeException( const std::string  &desc ) :
-//       DbgException( desc )
-//       {}
-//    
-//    static
-//    void
-//    exceptionTranslate(const TypeException  &e );
-//
-//};
-//
-///////////////////////////////////////////////////////////////////////////////////
-//
-//class IndexException : public DbgException
-//{
-//public:
-//
-//    IndexException() :
-//       DbgException( "Index out of range" )
-//       {}        
-//    
-//    static
-//    void
-//    translate(const IndexException  &e ) {
-//        PyErr_SetString(PyExc_IndexError, "Index out of range");
-//    }
-//};
-//
-///////////////////////////////////////////////////////////////////////////////////
-//
-//class MemoryException : public DbgException
-//{
-//public:
-//
-//    MemoryException( ULONG64 targetAddr ) :
-//        m_targetAddress( targetAddr ),
-//        DbgException( MemoryException::DescMaker( targetAddr, false ).desc() )
-//        {}    
-//
-//    MemoryException( ULONG64 targetAddr, bool phyAddr ) :
-//        m_targetAddress( targetAddr ),
-//        DbgException( MemoryException::DescMaker( targetAddr, phyAddr ).desc() )
-//        {}    
-//       
-//    static
-//    void
-//    translate( const MemoryException &e );
-//    
-//    ULONG64
-//    getAddress() const {
-//        return m_targetAddress;
-//    }
-//    
-//private:    
-//        
-//    ULONG64     m_targetAddress;
-//    
-//    class DescMaker {
-//    public:
-//        DescMaker( ULONG64 addr, bool phyAddr )
-//        {
-//            std::stringstream   sstr;
-//            if ( phyAddr )
-//                sstr << "Memory exception at 0x" << std::hex << addr << " target physical address";
-//            else
-//                sstr << "Memory exception at 0x" << std::hex << addr << " target virtual address";                            
-//            m_desc = sstr.str();
-//        }   
-//        
-//        const std::string&
-//        desc() const {
-//            return m_desc;
-//        }
-//        
-//    private:
-//        std::string     m_desc;
-//    };
-//};
-//
-///////////////////////////////////////////////////////////////////////////////////
-//
-//extern  PyObject  *baseExceptionType;
-//extern  PyObject  *eventExceptionType;
-//extern  PyObject  *typeExceptionType;
-//extern  PyObject  *memoryExceptionType;
-//
-///////////////////////////////////////////////////////////////////////////////////
\ No newline at end of file
diff --git a/pykd/dbgext.cpp b/pykd/dbgext.cpp
index 128a741..5a6080b 100644
--- a/pykd/dbgext.cpp
+++ b/pykd/dbgext.cpp
@@ -786,53 +786,88 @@ BOOST_PYTHON_MODULE( pykd )
     python::scope().attr("diaAmd64Regs") = 
         genDict(pyDia::Symbol::amd64RegName, pyDia::Symbol::cntAmd64RegName);
 
-    // exception:
+   // exception:
 
     // wrapper for standart python exceptions
-    python::register_exception_translator<pykd::PyException>( &PyException::exceptionTranslate );
+    python::register_exception_translator<PyException>( &PyException::exceptionTranslate );
 
-#define _DECL_BASE_EXCEPT_STR   .def( "__repr__", &pykd::DbgException::print )
-
-    // base exception
-    python::class_<pykd::DbgException>  dbgExceptionClass( "BaseException",
-        "Pykd base exception class",
-        python::no_init );
-    dbgExceptionClass
-        .def( python::init<std::string>( python::args("desc"), "constructor" ) )
-        .def( "desc", &pykd::DbgException::getDesc,
-            "Get exception description" )
-        _DECL_BASE_EXCEPT_STR;
-    pykd::DbgException::setTypeObject( dbgExceptionClass.ptr() );
-    python::register_exception_translator<pykd::DbgException>( 
-        &pykd::DbgException::exceptionTranslate );
-
-    // DIA exceptions
-    python::class_<pyDia::Exception, python::bases<DbgException> > diaException( 
-        "DiaException", "Debug interface access exception", python::no_init);
-    diaException
-        .def( "hres", &pyDia::Exception::getRes )
-        _DECL_BASE_EXCEPT_STR;
-    pyDia::Exception::setTypeObject( diaException.ptr() );
-    python::register_exception_translator<pyDia::Exception>( 
-        &pyDia::Exception::exceptionTranslate );
+    // BaseException
+    ExceptionTranslator<DbgException>::setTypeObject( 
+        python::class_<DbgException>( "BaseException", "Pykd base exception class", python::no_init )
+            .def( "__str__", &DbgException::getDesc )
+            .def( "__repr__", &DbgException::getDesc )
+            .ptr()
+            );
+  
+    // DIA exception
+    ExceptionTranslator<pyDia::Exception>::setTypeObject(
+        python::class_<pyDia::Exception, python::bases<DbgException> >( 
+            "DiaException", "Debug interface access exception", python::no_init)
+            .ptr()
+            );
 
     // Memory exception
-    python::class_<pykd::MemoryException, python::bases<DbgException> > memException(
-        "MemoryException", "Target memory access exception class",
-        python::no_init );
-    memException.def( "getAddress", &pykd::MemoryException::getAddress, "Return a target address where the exception occurs" );
-    pykd::MemoryException::setTypeObject( memException.ptr() );
-    python::register_exception_translator<pykd::MemoryException>(
-        &pykd::MemoryException::exceptionTranslate );
+    ExceptionTranslator<MemoryException>::setTypeObject(
+        python::class_<MemoryException, python::bases<DbgException> >(
+            "MemoryException", "Target memory access exception class", python::no_init )
+            .def( "getAddress", &pykd::MemoryException::getAddress, "Return a target address where the exception occurs" )
+            .ptr()
+            );
 
-    // Wait debug event exception
-    python::class_<WaitEventException, python::bases<DbgException> > waitEventException( 
-        "WaitEventException", "Debug interface access exception", python::no_init);
-    waitEventException
-        _DECL_BASE_EXCEPT_STR;
-    WaitEventException::setTypeObject( waitEventException.ptr() );
-    python::register_exception_translator<WaitEventException>( 
-        &WaitEventException::exceptionTranslate );
+    // WaitEventException
+    ExceptionTranslator<WaitEventException>::setTypeObject(
+        python::class_<WaitEventException, python::bases<DbgException> >( 
+            "WaitEventException", "Debug interface access exception", python::no_init)
+            .ptr()
+            );
+
+    
+
+
+
+//
+//#define _DECL_BASE_EXCEPT_STR   .def( "__repr__", &pykd::DbgException::print )
+//
+//    // base exception
+//    python::class_<pykd::DbgException>  dbgExceptionClass( "BaseException",
+//        "Pykd base exception class",
+//        python::no_init );
+//    dbgExceptionClass
+//        .def( python::init<std::string>( python::args("desc"), "constructor" ) )
+//        .def( "desc", &pykd::DbgException::getDesc,
+//            "Get exception description" )
+//        _DECL_BASE_EXCEPT_STR;
+//    pykd::DbgException::setTypeObject( dbgExceptionClass.ptr() );
+//    python::register_exception_translator<pykd::DbgException>( 
+//        &pykd::DbgException::exceptionTranslate );
+//
+//    // DIA exceptions
+//    python::class_<pyDia::Exception, python::bases<DbgException> > diaException( 
+//        "DiaException", "Debug interface access exception", python::no_init);
+//    diaException
+//        .def( "hres", &pyDia::Exception::getRes )
+//        _DECL_BASE_EXCEPT_STR;
+//    pyDia::Exception::setTypeObject( diaException.ptr() );
+//    python::register_exception_translator<pyDia::Exception>( 
+//        &pyDia::Exception::exceptionTranslate );
+//
+//    // Memory exception
+//    python::class_<pykd::MemoryException, python::bases<DbgException> > memException(
+//        "MemoryException", "Target memory access exception class",
+//        python::no_init );
+//    memException.def( "getAddress", &pykd::MemoryException::getAddress, "Return a target address where the exception occurs" );
+//    pykd::MemoryException::setTypeObject( memException.ptr() );
+//    python::register_exception_translator<pykd::MemoryException>(
+//        &pykd::MemoryException::exceptionTranslate );
+//
+//    // Wait debug event exception
+//    python::class_<WaitEventException, python::bases<DbgException> > waitEventException( 
+//        "WaitEventException", "Debug interface access exception", python::no_init);
+//    waitEventException
+//        _DECL_BASE_EXCEPT_STR;
+//    WaitEventException::setTypeObject( waitEventException.ptr() );
+//    python::register_exception_translator<WaitEventException>( 
+//        &WaitEventException::exceptionTranslate );
 
     DEF_PY_CONST_ULONG( DEBUG_CLASS_UNINITIALIZED );
     DEF_PY_CONST_ULONG( DEBUG_CLASS_KERNEL );
diff --git a/pykd/synsymbol.cpp b/pykd/synsymbol.cpp
index 75c40db..b8ffefe 100644
--- a/pykd/synsymbol.cpp
+++ b/pykd/synsymbol.cpp
@@ -42,7 +42,7 @@ void SyntheticSymbols::add(
             DEBUG_ADDSYNTHSYM_DEFAULT,
             &dbgModuleAndId);
     if ( FAILED( hres ) )
-        throw DbgException(buildExceptDesc("IDebugSymbols3::AddSyntheticSymbol", hres));
+        throw DbgException("IDebugSymbols3::AddSyntheticSymbol", hres);
 
     // add/update symbol for target module (in internal map)
     SymbolsScopedLock lock(*m_allSymbolsLock);
@@ -93,7 +93,7 @@ ULONG SyntheticSymbols::removeByMask(
             moduleName + "!" + symName,
             dbgSymbols);
     if (FAILED(hres))
-        throw DbgException(buildExceptDesc("IDebugSymbols3::GetSymbolEntriesByName", hres));
+        throw DbgException("IDebugSymbols3::GetSymbolEntriesByName", hres);
 
     if (dbgSymbols.empty())
         return 0;
diff --git a/pykd/synsymhelpers.cpp b/pykd/synsymhelpers.cpp
index 8f1b067..55b9fe0 100644
--- a/pykd/synsymhelpers.cpp
+++ b/pykd/synsymhelpers.cpp
@@ -69,7 +69,7 @@ SyntheticSymbols::ModuleId SynSymHelper::modByBase(ULONG64 moduleBase)
             0,
             &dbgModuleParameters);
     if ( FAILED( hres ) )
-        throw DbgException(buildExceptDesc("IDebugSymbols3::GetModuleParameters", hres));
+        throw DbgException( "IDebugSymbols3::GetModuleParameters", hres );
 
     return SyntheticSymbols::ModuleId(dbgModuleParameters);
 }
@@ -84,7 +84,7 @@ SyntheticSymbols::ModuleId SynSymHelper::modByOffset(
     HRESULT hres = 
         m_symbols.GetModuleByOffset(moduleOffset, 0, NULL, &moduleBase);
     if ( FAILED( hres ) )
-        throw DbgException(buildExceptDesc("IDebugSymbols3::GetModuleByOffset", hres));
+        throw DbgException( "IDebugSymbols3::GetModuleByOffset", hres );
 
     return modByBase(moduleBase);
 }