反序列化XML时出现FileNotFoundException异常

10
最近我们在反序列化XML时发现偶尔会抛出FileNotFoundException异常。错误信息为无法找到用于从XML到代码映射的临时程序集。从this文档中可以看出,当.NET Framework无法创建此文件时,就会发生这种情况(但即使在内部异常中也没有捕获原因)。以下是异常信息:
Type : System.IO.FileNotFoundException, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
Message : Could not find file 'C:\Documents and Settings\user\Local Settings\Temp\c5_nfoko.dll'.

文件名在每个错误中都不同,但错误始终相同,它起源于这里(完整的调用堆栈在底部):
at System.Xml.Serialization.XmlSerializer.GenerateTempAssembly(XmlMapping xmlMapping, Type type, String defaultNamespace)
at System.Xml.Serialization.XmlSerializer..ctor(Type type, String defaultNamespace)
at System.Xml.Serialization.XmlSerializer..ctor(Type type)

CSharpCodeGenerator尝试生成程序集时,我们已经在生产中使用这个代码多年了,它一直非常稳定。但是最近一周开始出现错误。我们想知道是否与最新的Microsoft安全补丁有关,因为它影响了我们在多个操作系统(XP和Server 2003)上的.NET 2.0和.NET 4.0版本的代码。
这个错误是不规律的,再次运行该进程通常会使其消失。这是一个单线程命令行应用程序,它检索文件并将它们插入到数据库中。
我没有找到其他遇到同样问题的人,但这并不是只有同一行代码才会出现的问题,我们有几个地方使用了System.Xml.Serialization代码,并且我们从每个地方都看到了这个错误。这段代码也不是我们最近更改过的。
我能找到的最接近的帖子是this
在我们的QA VM上没有病毒扫描程序,所以我认为这不是问题所在。我们还在我们托管的环境和另一个客户站点中看到了这个问题。
我们尝试过:
1. 清理此临时目录 2. 检查临时目录的权限(用户是本地管理员) 3. 通过使用sgen.exe生成XmlSerializers.dll并将其部署到应用程序文件夹中(问题仍然存在,好像.NET Framework不想使用这些程序集)。
如果有任何想法或建议,那将非常有帮助。
完整的调用堆栈:
Type : System.IO.FileNotFoundException, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
Message : Could not find file 'C:\Documents and Settings\user\Local Settings\Temp\c5_nfoko.dll'.
Source : mscorlib
Help link : 
FileName : C:\Documents and Settings\user\Local Settings\Temp\c5_nfoko.dll
FusionLog : 
Data : System.Collections.ListDictionaryInternal
TargetSite : Void WinIOError(Int32, System.String)
Stack Trace :    at System.IO.__Error.WinIOError(Int32 errorCode, String maybeFullPath)
at System.IO.FileStream.Init(String path, FileMode mode, FileAccess access, Int32 rights, Boolean useRights, FileShare share, Int32 bufferSize, FileOptions options, SECURITY_ATTRIBUTES secAttrs, String msgPath, Boolean bFromProxy)
at System.IO.FileStream..ctor(String path, FileMode mode, FileAccess access, FileShare share)
at Microsoft.CSharp.CSharpCodeGenerator.FromFileBatch(CompilerParameters options, String[] fileNames)
at Microsoft.CSharp.CSharpCodeGenerator.FromSourceBatch(CompilerParameters options, String[] sources)
at Microsoft.CSharp.CSharpCodeGenerator.System.CodeDom.Compiler.ICodeCompiler.CompileAssemblyFromSourceBatch(CompilerParameters options, String[] sources)
at System.CodeDom.Compiler.CodeDomProvider.CompileAssemblyFromSource(CompilerParameters options, String[] sources)
at System.Xml.Serialization.Compiler.Compile(Assembly parent, String ns, XmlSerializerCompilerParameters xmlParameters, Evidence evidence)
at System.Xml.Serialization.TempAssembly.GenerateAssembly(XmlMapping[] xmlMappings, Type[] types, String defaultNamespace, Evidence evidence, XmlSerializerCompilerParameters parameters, Assembly assembly, Hashtable assemblies)
at System.Xml.Serialization.TempAssembly..ctor(XmlMapping[] xmlMappings, Type[] types, String defaultNamespace, String location, Evidence evidence)
at System.Xml.Serialization.XmlSerializer.GenerateTempAssembly(XmlMapping xmlMapping, Type type, String defaultNamespace)
at System.Xml.Serialization.XmlSerializer..ctor(Type type, String defaultNamespace)
at System.Xml.Serialization.XmlSerializer..ctor(Type type)

一个 .Net 2.0 应用程序读取一个 .Net 4.0 序列化文件会受到影响吗? - Austin Salonen
你说过:“通过使用sgen.exe生成XmlSerializers.dll并将它们部署到应用程序文件夹中(问题仍然存在,好像.NET Framework不想使用这些程序集)。”- 你是让框架自己选择程序集还是直接在代码中引用它? - cvbarros
我认为,这篇帖子描述了问题:https://dev59.com/-HNA5IYBdhLWcg3wAI3e - Hannes
实际上,那篇帖子和Carlos提供的信息帮助我拼凑出了一些看起来可行的东西。通过在被反序列化的类中引用XmlSerializerAssemblyAttribute,它似乎可以使用我的XmlSerializers.dll程序集。我还需要进行更多的测试,但我们能够相当可靠地重现另一个错误,并且自从部署了带有此属性的新代码(dll)以来,我就没有再看到它了。 - Loathian
1
这是帮助我的具体帖子链接:https://dev59.com/-HNA5IYBdhLWcg3wAI3e#1642941 - Loathian
显示剩余4条评论
3个回答

1

我在ASP.NET中几乎遇到了同样的问题。原因是在该文件夹中编写的临时DLL被某个地方记住了,可能是其他临时DLL的引用。

解决办法是删除C:\Documents and Settings\user\Local Settings\Temp文件夹中的所有文件。其中一些文件可能被锁定,你需要进行多次迭代删除文件,因为被锁定的文件很可能是问题的源头(根据我的经验)。当临时文件夹清空后,一切都会按照预期工作(至少对我来说是这样)。


我们尝试清理临时文件夹,但问题仍然存在。问题似乎是csc.exe在运行时无法将临时.cs文件转换为程序集的失败,但这是不稳定的。 - Loathian

0
最近我在以系统服务(SYSTEM用户)的身份运行进程时遇到了这个问题。在我的情况下,问题是C:\Windows\TEMP文件夹具有只读属性。清除此属性解决了问题。

0

微软的XML序列化器本身非常糟糕。您收到的异常是因为.NET在每次创建新的XML序列化器时都会动态生成程序集。为尽可能避免这种情况发生,实现一个字典,将要序列化的类型作为键,XML序列化器作为值。这种缓存策略只会让您在首次序列化未知类型时遇到第一次机会异常。

请查看微软的MSDN网站上的XmlSerializer Class。其中有一段话告诉您我刚才说的内容。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接