Tuesday, November 8

如何在VCExpress下安装WTL

1,从MSDN http://msdn.microsoft.com/vstudio/express/visualc/ 下载并安装VCExpress 2005
2,按照MSDN的指示安装PSDK, 并且修改VCExpress的相关文件 http://msdn.microsoft.com/vstudio/express/visualc/usingpsdk/default.aspx ,
3,在修改VCExpress的Visual C++目录时添加下面的目录
Include files: C:\Program Files\Microsoft Platform SDK\include\atl
4, 修改PSDK的atl目录下的atlwin.h和atlbase.h文件

修改atlwin.h的1725行的SetChainEntry函数,将第一个for循环里的int i;定义提前。
---------------------------------------------------------------
BOOL SetChainEntry(DWORD dwChainID, CMessageMap* pObject, DWORD dwMsgMapID = 0)
{
int i;
// first search for an existing entry

for(i = 0; i < m_aChainEntry.GetSize(); i++)
---------------------------------------------------------------

修改atlbase.h的287行的AllocStdCallThunk和FreeStdCallThunk函数,将元代码注释,用新的宏代替。
---------------------------------------------------------------
/* Comment it
PVOID __stdcall __AllocStdCallThunk(VOID);
VOID __stdcall __FreeStdCallThunk(PVOID);

#define AllocStdCallThunk() __AllocStdCallThunk()
#define FreeStdCallThunk(p) __FreeStdCallThunk(p)

#pragma comment(lib, "atlthunk.lib")
*/
#define AllocStdCallThunk() HeapAlloc(GetProcessHeap(),0,sizeof(_stdcallthunk))
#define FreeStdCallThunk(p) HeapFree(GetProcessHeap(), 0, p)
---------------------------------------------------------------

3,下载并安装WTL http://wtl.sf.net
4, 下载WTL for VCExpress Wizard, 拷贝到WTL的AppWiz目录下,并双击安装WTL Wizard到VCExpress
WTL for VCExpress Wizard

enjoy VCExpress&WTL

Monday, November 7

如何在ASP.NET的CustomErrorPage里捕捉UnhandledException

我们知道ASP.NET的web.config里面可以设置CustomErrorPage,就像下面这个样子。

<customErrors mode="On" defaultRedirect="errorpage.aspx" >
<error statusCode="404" redirect="error404.aspx"></error>
</customErrors>

可是你在其他的aspx程序里抛出一个异常,在errorpage.aspx里并不能被捕捉到
in WebForm1.aspx
private void Button1_Click(object sender, System.EventArgs e)
{
throw new Exception("A Error Raised");
}

in errorpage.aspx
private void Page_Load(object sender, System.EventArgs e)
{
Exception ex = Server.GetLastError(); //这里永远返回null
if( ex!=null )
{
Label1.Text+= ex.Message;
}
}

google到一个解决方案:Custom Error Pages in ASP.NET

正像作者mattwag所说在Application_Error 以后会开始一个新的Session,即使Server里曾经存在的LastError也失去了踪影。
WebForm1.aspx抛出的异常最终会被global.asax的Application_Error处理,在这里如果没有Server.ClearError();的话,那么就会跳到在Web.config里指定的CustomErrorPage,但是异常的细节并没有办法直接获得。
mattwag将异常信息保存在session里,然后使用Server.Transfer使得session不被刷新,来达到目的。

这让我想到另一个比较简单的方案就是使用Application来保存异常信息,如下:

in global.asax.cs
protected void Application_Error(Object sender, EventArgs e)
{
Exception ex = Server.GetLastError().InnerException;
Application["UnhandledException"]=ex;
}

in errorpage.aspx
private void Page_Load(object sender, System.EventArgs e)
{
Exception ex = (Exception)Application["UnhandledException"];
Application.Remove("UnhandledException");
if( ex!=null )
{
//Write your code here like
//Label1.Text+= ex.Message;
}
}

适当地配置web.config和书写errorpage.aspx可以达到你需要的效果。
比如使用在子目录下的错误处理页。
<customerrors mode="On" defaultredirect="~/Subfolder/CustomErrorPage.aspx">
</customerrors>