重启软件后修改密码触发File access exception问题排查求助
分析与解决方案
看起来你的密码修改功能遇到了一个典型的文件访问问题,结合代码和现象来看,主要有几个可能的原因,我们逐一分析并给出修复方案:
1. 相对路径导致的文件位置不一致
你代码中使用的是相对路径"UserData.txt",软件重启后当前工作目录可能发生变化(比如首次运行在安装目录,注销重启后工作目录切换到了用户临时目录或文档目录),这会导致:
- 首次修改密码时,文件被写入到初始工作目录
- 重启后,软件尝试在新的工作目录读取/写入文件,要么找不到文件,要么没有该目录的写入权限,从而抛出
File access exception
修复方案:使用绝对路径来定位用户数据文件,比如基于应用程序的安装目录:
// 获取应用程序的根目录 string appDir = AppDomain.CurrentDomain.BaseDirectory; // 拼接绝对路径 string userDataPath = Path.Combine(appDir, "UserData.txt");
之后所有文件操作都使用userDataPath替代相对路径。
2. 重复读取文件可能引发的锁定冲突
你的代码中连续调用了File.ReadAllText()和File.ReadAllLines(),虽然这两个方法都会自动释放文件句柄,但在某些系统环境下,短时间内两次打开同一个文件可能触发临时锁定,尤其是重启后系统文件缓存状态变化时,更容易出现异常。
修复方案:只读取一次文件,复用读取结果:
// 只读取一次文件内容到数组 string[] userDataBase = File.ReadAllLines(userDataPath); // 从数组生成字符串,避免再次读取文件 string userDataBaseString = string.Join(Environment.NewLine, userDataBase);
3. StreamWriter的默认文件访问模式可能存在锁定问题
默认的StreamWriter构造函数会以独占模式打开文件,如果重启后有其他进程(比如杀毒软件、系统索引服务)正在访问该文件,就会抛出访问异常。我们可以显式指定文件的共享模式,允许其他进程读取:
修复方案:改用FileStream创建StreamWriter,设置共享权限:
using (var fs = new FileStream(userDataPath, FileMode.Create, FileAccess.Write, FileShare.Read)) using (var writer = new StreamWriter(fs)) { int i1 = 0; while (i1 != userDataBase.Length) { writer.WriteLine(userDataBase[i1]); i1++; } }
完整修复后的代码示例
整合以上所有修复点,你的ChangePassword方法可以修改为:
void ChangePassword() { // 使用绝对路径定位用户数据文件 string appDir = AppDomain.CurrentDomain.BaseDirectory; string userDataPath = Path.Combine(appDir, "UserData.txt"); // 只读取一次文件,复用数据 string[] userDataBase = File.ReadAllLines(userDataPath); string userDataBaseString = string.Join(Environment.NewLine, userDataBase); string newPassHash = MD5Hash(NewPassworTxBx.Text); if (userDataBaseString.Contains(newPassHash)) { MessageBox.Show("That password is already in use"); return; } string targetUserLine = GlobalVar.UserNameEntered.PadRight(20, ' ') + MD5Hash(CurrentPasswordTxBx.Text); for (int i = 0; i < userDataBase.Length; i++) { // MessageBox.Show(userDataBase[i]); // 调试代码可保留,正式环境建议移除 if (userDataBase[i] == targetUserLine) { string usr = userDataBase[i].Substring(0, 20); userDataBase[i] = usr + newPassHash; // MessageBox.Show(userDataBase[i].ToString()); // 调试代码可保留 // 使用带共享权限的FileStream写入文件 using (var fs = new FileStream(userDataPath, FileMode.Create, FileAccess.Write, FileShare.Read)) using (var writer = new StreamWriter(fs)) { foreach (string line in userDataBase) { writer.WriteLine(line); } } MessageBox.Show("Password changed to: " + NewPassworTxBx.Text); break; } } }
额外建议
- 移除代码中的调试用
MessageBox,避免影响用户体验 - 考虑使用更安全的哈希算法替代MD5(比如SHA-256),并添加随机盐值,提升密码安全性
- 增加异常捕获逻辑,比如用
try-catch包裹文件操作,给出更友好的错误提示
内容的提问来源于stack exchange,提问作者Lewis Dixon
相关产品推荐
相关产品推荐

