【发布时间】:2018-08-21 22:57:14
【问题描述】:
这是一个棘手的问题。我怀疑这需要一些文件系统的高级知识才能回答。
我有一个面向 .NET 框架 4.0 的 WPF 应用程序“App1”。它有一个Settings.settings 文件,该文件生成一个标准的App1.exe.config 文件,其中存储了默认设置。当用户修改设置时,修改进入AppData\Roaming\MyCompany\App1\X.X.0.0\user.config。这都是标准的 .NET 行为。但是,有时我们会发现客户计算机上的 user.config 文件不是应有的文件,这会导致应用程序崩溃。
问题看起来像这样:user.config 的大小与使用 XML 填充时的大小差不多,但不是 XML,它只是一堆 NUL 字符。这是字符 0 一遍又一遍地重复。我们没有关于导致此文件修改的原因的信息。
如果我们删除user.config,我们可以在客户的设备上解决该问题,因为公共语言运行时只会生成一个新的。他们将丢失对设置所做的更改,但可以再次进行更改。
但是,我在另一个 WPF 应用程序“App2”中遇到了这个问题,该应用程序还有另一个 XML 文件 info.xml。这次不同了,因为文件是由我自己的代码生成的,而不是由 CLR 生成的。共同的主题是两者都是 C# WPF 应用程序,都是 XML 文件,并且在这两种情况下,我们都完全无法在测试中重现问题。这可能与 C# 应用程序与 XML 文件或一般文件交互的方式有关吗?
我们不仅无法在当前应用程序中重现问题,而且我什至无法通过编写故意生成错误的自定义代码来重现问题。我找不到导致文件被空值填充的单个 XML 序列化错误或文件访问错误。那么会发生什么?
App1 通过调用Upgrade() 和Save() 以及获取和设置属性来访问user.config。例如:
if (Settings.Default.UpgradeRequired)
{
Settings.Default.Upgrade();
Settings.Default.UpgradeRequired = false;
Settings.Default.Save();
}
App2 通过序列化和反序列化 XML 来访问info.xml:
public Info Deserialize(string xmlFile)
{
if (File.Exists(xmlFile) == false)
{
return null;
}
XmlSerializer xmlReadSerializer = new XmlSerializer(typeof(Info));
Info overview = null;
using (StreamReader file = new StreamReader(xmlFile))
{
overview = (Info)xmlReadSerializer.Deserialize(file);
file.Close();
}
return overview;
}
public void Serialize(Info infoObject, string fileName)
{
XmlSerializer writer = new XmlSerializer(typeof(Info));
using (StreamWriter fileWrite = new StreamWriter(fileName))
{
writer.Serialize(fileWrite, infoObject);
fileWrite.Close();
}
}
我们在 Windows 7 和 Windows 10 上都遇到过这个问题。在研究这个问题时,我发现了这篇文章,在 Windows 8.1 中遇到了同样的 XML 问题:Saved files sometime only contains NUL-characters
我可以在我的代码中进行更改以防止这种情况发生吗,或者问题是否存在于 .NET 的行为中?
在我看来有三种可能:
- CLR 正在将空字符写入 XML 文件。
- 文件的内存地址指针在不移动文件内容的情况下切换到另一个位置。
- 文件系统尝试将文件移动到另一个内存地址并且文件内容被移动但指针没有得到更新。
我觉得 2 和 3 比 1 更有可能。这就是为什么我说这可能需要高级文件系统知识。
如果有任何信息可以帮助我重现、修复或解决问题,我将不胜感激。谢谢!
【问题讨论】:
-
在写入该文件时可能出现断电(例如当您强行关闭计算机时)?在这种情况下,我认为可能会出现像您这样的情况。
-
我会将 using 语句替换为 Try/Catch 并将结果保存到日志文件中。 using 语句隐藏了异常,因此您不知道发生了异常,并且代码将继续执行,就像没有出错一样。
-
@jdweng 虽然我当然应该尝试使用 try/catch 收集诊断数据,但我不相信
using语句会抑制异常。我可以在using块内生成异常就好了。 -
虽然 CLR 中可能有一些可怕的 bug 导致了这个问题,但所涉及的逻辑非常简单,而且影响非常大,以至于你希望这样的 bug 被发现并且现在已经修复(尽管这当然不是硬性保证)。我的钱用于文件系统过滤器驱动程序损坏导致的文件损坏。询问您的客户安装了哪种防病毒/反恶意软件。另外,询问他们是否使用了真正的漫游配置文件,即上传到网络并跨机器传输的那种——这显然是另一个失败点。
-
我也有类似的问题,我已经把问题贴在这里stackoverflow.com/questions/49269579/…希望我们能得到解决方案
标签: c# xml filesystems ntfs null-character