C# 在CommonApplicationData中存储配置文件时出现间歇性未经授权的数据访问异常

C# 在CommonApplicationData中存储配置文件时出现间歇性未经授权的数据访问异常,c#,.net,windows,C#,.net,Windows,我构建了一个应用程序,它在环境.SpecialFolder.CommonApplicationData下有一个本地配置存储。(存储为每台计算机,因为它反映了与PC配对的无线设备中的配置更改。)清单中标记了我的安装程序以管理员身份运行,并使用以下例程创建子目录: private static void CreateAndPermit(SecurityIdentifier securityIdentifier, String path) { DirectoryInfo info = new

我构建了一个应用程序,它在
环境.SpecialFolder.CommonApplicationData
下有一个本地配置存储。(存储为每台计算机,因为它反映了与PC配对的无线设备中的配置更改。)清单中标记了我的安装程序以管理员身份运行,并使用以下例程创建子目录:

private static void CreateAndPermit(SecurityIdentifier securityIdentifier, String path)
{
    DirectoryInfo info = new DirectoryInfo(path);
    if (!info.Exists)
        info.Create();

    DirectorySecurity security = info.GetAccessControl();
    AccessRule rule = new FileSystemAccessRule(securityIdentifier,
            FileSystemRights.Write |
            FileSystemRights.ReadAndExecute |
            FileSystemRights.Modify |
            FileSystemRights.CreateFiles,
            InheritanceFlags.ContainerInherit | InheritanceFlags.ObjectInherit,
            PropagationFlags.InheritOnly,
            AccessControlType.Allow);
    bool modified;
    security.ModifyAccessRule(AccessControlModification.Add, rule, out modified);
    info.SetAccessControl(security);
}
这将创建一个目录,桌面用户可以使用资源管理器访问该目录,并且我的应用程序可以在其中写入配置数据。然后,我的应用程序代码尝试按以下顺序更新配置文件(不使用
file.Replace
,因为我已经分解了调试步骤):

此代码间歇性地(在我的开发计算机上从未出现过)抛出System.UnauthorizedAccessException,通常在删除备份文件的步骤上抛出。异常浏览器指示“每个人”对除“特殊权限”之外的所有内容都有权限


我得到的唯一线索是,一个终端用户在将XP Pro机器从独立登录切换到使用域后遇到了问题。

这就是在多任务操作系统上运行代码的危险,无法保证您打开或使用的文件不被其他进程使用。想想搜索索引器、病毒扫描器、工具栏。或者只是用户开始查看文件的另一个进程。包括程序的另一个实例

假设这样的程序对.bak文件不感兴趣,那么在用户第二次保存文件时,删除.bak文件将不起作用。其他进程在原始文件上打开了句柄。将文件重命名为.bak不会有问题。删除它将是一个错误


假设失败,捕获IOException并告诉用户它现在无法工作。用户的IT人员知道如何使用(比如)SysInternals的Handle实用程序来找出谁锁定了文件。

病毒扫描程序或其他后台进程是一种有趣的可能性。不幸的是,该文件是一个XML数据库,当用户拖放配置项时,它会在后台更新。用户从不显式保存文件,如果系统正常工作,则用户不知道应用程序持久性是如何实现的。今天,测试人员在行动中发现它被svchost锁定,几乎可以肯定是代表Symantec。有没有最终解决方案的源代码示例?
    if (File.Exists(filename + ".bak"))
        File.Delete(filename + ".bak");
    if (File.Exists(filename))
        File.Move(filename, filename + ".bak");
    File.Move(tmpfile, filename);