XmlSerializer

在最近的一个ASP.NET项目中,菜单是动态产生的。但客户要求能随时改动这菜单,虽然这样的改动不是经常性的,但他们需要有这样的灵活性。我们不指望,也不希望他们直接修改数据库,也没打算另设一个专门界面供他们修改菜单数据,所以我们把菜单数据放在了一个XML文件里。如果他们需要改动菜单的话,管理页面的人只要修改这XML文件即可。

考虑到性能问题,我们将该文件里的数据做了缓存,并且对该缓存建立了对那XML文件的依赖性。如果那个XML文件被改动的话,我们重新装载数据。在程序中,通过XmlSerializer从该缓存中的数据来生成对象,做个人化的处理后,进一步生成菜单。测试运行时,甚至做压力测试时一直很可靠。

项目正式推出后,一开始没问题,能承受的共时用户数也满足要求。突然有一天,网站不能访问了,但能登陆那台网络服务器的机器。关闭aspnet_wp.exe进程或重启网络服务器后,网站又能正常运行,但过几天后,同样的问题又会发生。我们是用微软的Exception Management Application Block来记录Exception的,问题发生时,我们发现在Event Viewer Application Log里有类似这样的一个记录,

…..Cannot execute a program. The command being executed was “c:\winnt\microsoft.net\framework\v1.1.4322\csc.exe” /noconfig @”C:\WINNT\Microsoft.NET\Framework\v1.1.4322\Temporary ASP.NET Files\OurAppName\8f217464\4023a27\npbqe25u.cmdline”.]
System.CodeDom.Compiler.Executor.ExecWaitWithCaptureUnimpersonated(IntPtr userToken, String cmd, String currentDir, TempFileCollection tempFiles, String& outputName, String& errorName, String trueCmdLine) +2036
…..

后面还有一堆别的Exception记录,但看样子都是这个Exception的衍生物。

What the heck is this? 我们的项目是用VB.NET写的,怎么会跟csc.exe有关?Google了一下,在微软的KB里发现这篇文章

BUG: “ExternalException: Cannot Execute a Program” Error Message When You Call WebServices from .aspx Page

跟WebServices有关?我们没用WebServices啊

再查,有个人也有类似问题,

Cannot execute a program. The command being executed … Error

据说跟IIS Lockdown tool有关。但我们是内部网络,也没有用IIS Lockdown tool啊。根据上述KB文章的建议,我们给予IUSR_机器名 以及 IWAM_机器名充分的权限,问题依旧。

最后向微软支持中心求救,他们的解释是,每次生成带有XmlAttributeOverrides属性或类参数的XmlSerializer对象时, C#编译器就会被调用,导致memory增加,时间长了,就会产生上述问题。他们建议在Application对象里缓存一个XmlSerializer对象,在以后的调用中重用该XmlSerializer对象,sounds like an ugly solution to me

那部分使用XmlSerializer对象的编码是项目早期就完成的,没想到会造成这样的问题。一气之下,用另外的方法重写了菜单类,问题解决。