近期开始替同事维护一个WinForm的工具软件,在VS2005下用C#开发的。源代码拿过来后,重编译了一遍,运行正常,代码写的也很规范。随后根据用户需求,我陆续在后台代码中加了几个功能,还算顺利。前几天又要对主界面进行修改,突然发现无法在视窗设计器中打开MainForm了,IDE提示“分析 EntityName 时出错。 行 2,位置 47。”!
最初,我认为是视窗设计器解析MainForm.Design.cs文件时出错,导致界面无法显示,但遍查文件,没有发现任何语法错误,编译正常通过。随后怀疑是VS2005的问题。由于我的台式机中安装了VS2005和2008两个版本,近一年多2005几乎没有用过,会不会是它的某个文件损坏引起了设计器的问题?于是改用2008查看,竟还是出现同样的结果。再把源码拷贝到我的笔记本上,用里面的2008查看,报错依旧。不可能两台机器的2005和2008同时歇菜吧?!无奈之下,在另一个同事的电脑上继续打开。咦,这回无论是2005还是2008,又都没问题了。由此看来,与IDE无关。我又看了一边报错的详细信息,出错时的调用堆栈是:在 System.Xml.XmlTextReaderImpl.Throw(Exception e)在 System.Xml.XmlTextReaderImpl.Throw(String res, String arg)在 System.Xml.XmlTextReaderImpl.ParseEntityName()在 System.Xml.XmlTextReaderImpl.ParseAttributeValueSlow(Int32 curPos, Char quoteChar, NodeData attr)在 System.Xml.XmlTextReaderImpl.ParseAttributes()在 System.Xml.XmlTextReaderImpl.ParseElement()在 System.Xml.XmlTextReaderImpl.ParseElementContent()在 System.Xml.XmlTextReaderImpl.Read()在 System.Xml.XmlTextReader.Read()在 Microsoft.VisualStudio.Design.VSTypeResolutionService.GeneratedAssemblyEntry.RealizeMoniker(String moniker)在 Microsoft.VisualStudio.Design.VSTypeResolutionService.GeneratedAssemblyEntry.get_FileName()在 Microsoft.VisualStudio.Design.VSTypeResolutionService.AssemblyEntry.get_Assembly()在 Microsoft.VisualStudio.Design.VSTypeResolutionService.GeneratedAssemblyEntry.get_Assembly()在 Microsoft.VisualStudio.Design.VSTypeResolutionService.AssemblyEntry.Search(String fullName, String typeName, Boolean ignoreTypeCase, Assembly& assembly, String description)在 Microsoft.VisualStudio.Design.VSTypeResolutionService.SearchGeneratedEntries(AssemblyName assemblyName, String typeName, Boolean ignoreTypeCase, Assembly& assembly)在 Microsoft.VisualStudio.Design.VSTypeResolutionService.SearchEntries(AssemblyName assemblyName, String typeName, Boolean ignoreCase, Assembly& assembly, ReferenceType refType)在 Microsoft.VisualStudio.Design.VSTypeResolutionService.GetType(String typeName, Boolean throwOnError, Boolean ignoreCase, ReferenceType refType)在 Microsoft.VisualStudio.Design.Serialization.CodeDom.AggregateTypeResolutionService.GetType(String name, Boolean throwOnError, Boolean ignoreCase)在 Microsoft.VisualStudio.Design.Serialization.CodeDom.AggregateTypeResolutionService.GetType(String name, Boolean throwOnError)在 System.ComponentModel.Design.Serialization.CodeDomSerializerBase.GetType(ITypeResolutionService trs, String name, Dictionary`2 names)在 System.ComponentModel.Design.Serialization.CodeDomSerializerBase.FillStatementTable(IDesignerSerializationManager manager, IDictionary table, Dictionary`2 names, CodeStatementCollection statements, String className)在 System.ComponentModel.Design.Serialization.TypeCodeDomSerializer.Deserialize(IDesignerSerializationManager manager, CodeTypeDeclaration declaration)在 System.ComponentModel.Design.Serialization.CodeDomDesignerLoader.PerformLoad(IDesignerSerializationManager manager)在 Microsoft.VisualStudio.Design.Serialization.CodeDom.VSCodeDomDesignerLoader.PerformLoad(IDesignerSerializationManager serializationManager)在 Microsoft.VisualStudio.Design.Serialization.CodeDom.VSCodeDomDesignerLoader.DeferredLoadHandler.Microsoft.VisualStudio.TextManager.Interop.IVsTextBufferDataEvents.OnLoadCompleted(Int32 fReload)
看来与XML解析有关,于是开始上网找答案。一番百度之后,果然有眉目:有人提到如果在XML文件中出现了符号&,解析器会把它当转义字符处理...
于是我又遍查了解决方案了所有的XML文件,并没有发现令人头疼的&。正百思不得其解时,猛然发现这些代码是与一些相关的开发文档一起放在了一个名为“S&A”的目录中,这个目录名中的“&”会不会就是罪魁祸首?立刻动手,把目录名改成“SA”,于是“分析EntityName时出错”没有了,主窗体出现了,这个世界也清静了...现在回想起来,同事把源码给我时,命名为“Statistic_Analysis”,名字有点长。我把源码与其他开发文档归入了同一目录下,就取了个简单的名字:S&A。随后,无论是在我的台式机、笔记本中找问题时,都带着这个目录名,而在同事电脑上试验时,只把源码发了过去。所以出现了前面提到了奇怪现象。问题解决了,心情大好,我又在VS2010里试了一下,问题再没有复现,看来经历了2005、2008两个版本,微软已经在2010上彻底解决了这个BUG。 不知道有多少人和我一样受过视窗设计器与这个“&”的折磨?