| 本文对《AppLogger, 
                          a Simple Distributed Application Logger - Part 1, By 
                          sebma, http://www.codeproject.com/csharp/MaAppLogger.asp#xx870711xx》一文进行了分析,并在此基础上进行功能扩展(DBLogger 
                          & EmailLogger),同时将Remote Object移植到IIS环境。如果将Remote 
                          Object移植到IIS环境中,需要修改FileLogger,另外还会出现许多相关的问题。下面针对这些问题的原因及其解决办法分别进行介绍。 一般而言,在实际的应用系统中,由IIS承载Remote Object比较容易维护和管理,并且也比较稳定。关于如何将Remote 
                          Object部署在IIS下,可以参考《如何在IIS中承载远程对象》一文。 经过修改后的Application Logger based on .Net Remoting总体架构如下: 
 Client & Server Side共享AppRemotingLogger::BusinessFacade。Client只需要引用AppRemoting.BusinessFacade.dll,任何在BusinessRules和DataAccess层的修改对Client端没有影响。Server端可以根据需要修改Logger的类型。 注:AppRemotingLoggerHelp Class移到到Implementation/Client层,AppRemotingLoggerHelp实现对Remote 
                          Object的调用,并封装对各种类型Message的log操作,如Exception, Error, Warning, 
                          Info and Debug(Debug Message只有在调试阶段才记录日志)。 1. 主要类库分析 (1)BusinessRules Layer的Logger 
 FileLoger – 记录日志文件(text file)到指定的目录,每个Application有对应的日志文件。 EventLoger – 日志输出到Server端Event Viewer,个人觉得不是很实用。 DebugLogger - 记录日志输出到DebugView(最后的参考文档处提供有下载URL),如果Remote 
                          Object部署在IIS环境下,则失效。 ConsoleLogger – 如果Remote Object部署在IIS环境下,则失效。如果Remote 
                          Object由EXE承载,ConsoleLogger比较方便调试。 下面2个logger是我自己加进去的,代码比较简单,就不贴出来了。 EmailLogger – 以邮件的方式输出日志到指定的receiver。 DBLogger – 将日志记录到指定数据库的数据表中,个人觉得这个logger比较实用。 DefaultAppRemotingLogger – 实现IappLogger接口,调用LoggerFactory,并根据Web.config文件的设置生成Logger实体。 
 DefaultHome Class实现Ihome接口,并且是Client可以访问的Remote Object。从如下Web.config文件中可以看到: <wellknown  mode="SingleCall"  type="AppRemotingLogger.BusinessRules.DefaultHome, 
                          AppRemotingLogger.BusinessRules"  objectUri="AppRemotingLogger.IHome.soap" 
                          /> DefaultHome Class中GetAppLogger()方法调用DefaultAppRemotingLogger,返回Logger实例。 DefaultAppRemotingLogger Class调用LoggerFactory,并根据Web.config中 <add key="AppRemotingLogger.Type" value="AppRemotingLogger.BusinessRules.FileLogger" 
                          /> 的设定,生成Logger对象。 另外,DefaultAppRemotingLogger Class中LogMessage()方法通过使用线程池来实现异步记录日志,避免造成系统瓶颈。 
                         2. 如何调试部署在IIS中的Remote Object 为了调试部署在IIS中的Remote Object,需要将aspnet_wp进程附加进来(attach),这个在开发测试过程中非常重要。具体过程如下: (1)在client端设置断点,并进入调试状态。 (2)点击”Tools/Debug Processes…”,附加aspnet_wp进程。如下图所示: 注意,其中Name根据IIS服务运行的机器,选择/输入相应的computer name。 
 3. 需要注意的若干问题 DBLogger & EmailLogger的coding比较简单,这里省略了。不过在调试过程中,需要注意如下一些问题。 (I)EmailLogger可能存在“Could not access ‘CDO.Message’ object”异常 导致的原因及其解决办法: (1)SmtpServer等参数设置有问题,确保参数设置正确。 (2)因为Web.Mail需要调用CDOSYS.dll,有可能CDOSYS.dll没有注册好,可通过regsvr32 
                          /u 先取消注册,然后在用regsvr32在注册一次。 (3)如问题仍没有解决,可以尝试修改 C:\WINNT\Microsoft.NET\Framework\v1.1.4322\CONFIG目录下的machine.config文件,并将<processModel> 
                          Section中的UserName属性设置为SYSTEM。 其实,我使用默认的UserName=machine也可以成功的发送email。 (II)EventLogger可能存在“Requested registry access is not 
                          allowed”异常 导致的原因及其解决办法: ASP.Net账号没有足够的权限写Event List,只要将machine.config中的UserName属性设置为SYSTEM就可以解决了。不过,EventLogger其实不是很实用。 (III)FileLogger可能存在“Access to the path c:\winnt\system32\<filename> 
                          is denied”异常 导致的原因及其解决办法: FileLogger默认将日志记录在c:\winnt\system32\目录,ASP.NET帐户根本就没有对该目录的访问权限。因此,需要修改DataAccess项目中的LogFileDataWriter.cs文件。 public 
                          LogFile(string strFileName)  
                          {  
                                 
                          string strFileLoggerPath = ConfigurationSettings.AppSettings["FileLoggerPath"];  
                                 
                          if(strFileLoggerPath == null || strFileLoggerPath.Trim().Length 
                          == 0)  
                                 
                          {  
                                 
                                      
                          strFileLoggerPath = @"c:\Inetpub\wwwroot";  
                                 
                          }  
                             
                                 
                          strFileName = @strFileLoggerPath + strFileName;  
                                 
                          m_objFileStream = new FileStream(strFileName,  
                                 
                                      
                          FileMode.Append,  
                                 
                                      
                          FileAccess.Write,  
                                 
                                      
                          FileShare.Read);  
                          }
                         明确指定日志文件存放的路径"FileLoggerPath"(在web.config文件<appSettings>中设定),同时需要给予ASP.NET帐户对该目录的Full 
                          Control权限。 (IV)DebugLogger在IIS环境中失效,不过没有Exception抛出 的确如此,这个问题没有找到解决办法。不过关系不大,不使用DebugLogger就可以了。 DebugView可以从http://www.sysinternals.com/ntw2k/freeware/debugview.shtml下载。 我在测试EXE承载的Remote Object时,DebugView可以捕获到Trace消息,一切运行正常。但当Remote 
                          Object部署在IIS中后,DebugView就无法捕获到Trace消息了。 通过断点测试,Trace.WriteLine(objBuilder.ToString())语句是正确执行的,没有抛出异常。 (V)The remote server returned an error: (407) Proxy 
                          Authentication Required异常. 导致的原因及其解决办法: 一般而言是由于IE中设置采用Proxy,如果Disable IE proxy settings,应该就没有问题了。先测试一下,如果可行,则通过如下的code告诉HttpChannel不要访问Proxy 
                          Server Settings,来彻底上述解决。 HttpChannel theChannel = (HttpChannel)ChannelServices.GetChannel("http"); 
                         theChannel.Properties["proxyName"] = null; 将上面的2行代码放在获取Remote Object的代码后面。 我采用Activator.GetObject()方法来获取Remote Object,上述代码会出现Cast错误。对上述代码稍做修改如下: System.Runtime.Remoting.Channels.Http.HttpClientChannel 
                          theChannel = (System.Runtime.Remoting.Channels.Http.HttpClientChannel) 
                          ChannelServices.GetChannel("http"); theChannel.Properties["proxyName"] = null; 同样将上面的2行代码放在获取Remote Object的代码后面就可以了。 (VI)The underlying connection was closed: Unable to 
                          connect to the remote server异常. 可以从如下几个方面进行检测: (1)确认网络正常,并且在Client端可以通过IE访问到Remote Object。 (2)确认Client的应用程序的配置文件URL正确访问Remote Object。 |