You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

管理员权限下C#访问C:\Windows\System32\sru\SRUDB被拒绝的问题

解决UnauthorizedAccessException访问C:\Windows\System32\sru\SRUDB被拒的问题

核心原因分析

  • 文件系统重定向(64位系统):如果你的程序是32位,Windows会自动将C:\Windows\System32的访问重定向到C:\Windows\SysWOW64,但SRUDB文件实际位于原生System32目录,导致你访问的是错误路径,触发权限拒绝。
  • 操作顺序错误:代码中先尝试下载文件到目标路径,此时目标路径的文件可能未配置好权限,甚至被系统锁定,直接下载会先抛出异常。
  • 系统文件锁定:SRUDB是系统资源使用数据库文件,大概率被srums.exe等系统进程占用,直接读写或移动会被系统阻止。

解决方案

1. 禁用文件系统重定向(仅32位程序需要)

在访问System32路径前禁用重定向,操作完成后恢复:

[DllImport("kernel32.dll", SetLastError = true)]
static extern bool Wow64DisableWow64FsRedirection(ref IntPtr ptr);

[DllImport("kernel32.dll", SetLastError = true)]
static extern bool Wow64RevertWow64FsRedirection(IntPtr ptr);

2. 调整操作顺序

先配置目标目录和文件的权限,再将文件下载到临时目录,最后处理移动/替换操作,避免直接操作被锁定的系统文件。

3. 处理系统文件锁定

使用MoveFileEx设置延迟移动/删除,让系统在重启后完成操作,绕过当前进程的文件占用:

[DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
static extern bool MoveFileEx(string lpExistingFileName, string lpNewFileName, MoveFileFlags dwFlags);

[Flags]
enum MoveFileFlags
{
    MOVEFILE_DELAY_UNTIL_REBOOT = 0x00000004
}

修改后的代码示例

// 调用示例
DownloadAndMoveFile("https://test.com/SRUDB", @"C:\Windows\System32\sru", "SRUDB.dat");

private void DownloadAndMoveFile(string url, string targetDir, string newFileName)
{
    IntPtr redirectPtr = IntPtr.Zero;
    try
    {
        // 禁用64位文件系统重定向(仅32位程序需要)
        if (Environment.Is64BitOperatingSystem && !Environment.Is64BitProcess)
        {
            Wow64DisableWow64FsRedirection(ref redirectPtr);
        }

        // 确保目标目录存在并配置权限
        if (!Directory.Exists(targetDir))
        {
            Directory.CreateDirectory(targetDir);
            var dirSecurity = Directory.GetAccessControl(targetDir);
            var currentAccount = new NTAccount(WindowsIdentity.GetCurrent().Name);
            dirSecurity.AddAccessRule(new FileSystemAccessRule(
                currentAccount, 
                FileSystemRights.FullControl, 
                InheritanceFlags.ContainerInherit | InheritanceFlags.ObjectInherit, 
                PropagationFlags.None, 
                AccessControlType.Allow));
            Directory.SetAccessControl(targetDir, dirSecurity);
        }

        // 下载到临时文件,避免直接写入被锁定的目标路径
        string tempFilePath = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString());
        using (WebClient client = new WebClient())
        {
            client.DownloadFile(url, tempFilePath);
        }

        string targetFilePath = Path.Combine(targetDir, newFileName);
        string originalSRUDBPath = Path.Combine(targetDir, "SRUDB");

        // 配置原SRUDB文件权限(如果存在)
        if (File.Exists(originalSRUDBPath))
        {
            var fileSecurity = File.GetAccessControl(originalSRUDBPath);
            var currentAccount = new NTAccount(WindowsIdentity.GetCurrent().Name);
            fileSecurity.RemoveAccessRule(new FileSystemAccessRule(currentAccount, FileSystemRights.FullControl, AccessControlType.Deny));
            fileSecurity.AddAccessRule(new FileSystemAccessRule(currentAccount, FileSystemRights.FullControl, AccessControlType.Allow));
            File.SetAccessControl(originalSRUDBPath, fileSecurity);
        }

        // 配置目标文件权限(如果存在)
        if (File.Exists(targetFilePath))
        {
            var fileSecurity = File.GetAccessControl(targetFilePath);
            var currentAccount = new NTAccount(WindowsIdentity.GetCurrent().Name);
            fileSecurity.RemoveAccessRule(new FileSystemAccessRule(currentAccount, FileSystemRights.FullControl, AccessControlType.Deny));
            fileSecurity.AddAccessRule(new FileSystemAccessRule(currentAccount, FileSystemRights.FullControl, AccessControlType.Allow));
            File.SetAccessControl(targetFilePath, fileSecurity);
        }

        // 处理被锁定的文件,延迟到重启后操作
        if (File.Exists(targetFilePath))
        {
            MoveFileEx(targetFilePath, null, MoveFileFlags.MOVEFILE_DELAY_UNTIL_REBOOT);
        }

        // 移动临时文件到目标路径
        if (File.Exists(originalSRUDBPath))
        {
            MoveFileEx(originalSRUDBPath, targetFilePath, MoveFileFlags.MOVEFILE_DELAY_UNTIL_REBOOT);
        }
        else
        {
            File.Move(tempFilePath, targetFilePath);
        }
    }
    finally
    {
        // 恢复文件系统重定向
        if (Environment.Is64BitOperatingSystem && !Environment.Is64BitProcess && redirectPtr != IntPtr.Zero)
        {
            Wow64RevertWow64FsRedirection(redirectPtr);
        }
    }
}

// 导入必要的系统API
[DllImport("kernel32.dll", SetLastError = true)]
static extern bool Wow64DisableWow64FsRedirection(ref IntPtr ptr);

[DllImport("kernel32.dll", SetLastError = true)]
static extern bool Wow64RevertWow64FsRedirection(IntPtr ptr);

[DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
static extern bool MoveFileEx(string lpExistingFileName, string lpNewFileName, MoveFileFlags dwFlags);

[Flags]
enum MoveFileFlags
{
    MOVEFILE_DELAY_UNTIL_REBOOT = 0x00000004
}

额外注意事项

  • 确保程序清单中已设置requestedExecutionLevel level="requireAdministrator",强制以管理员身份运行。
  • SRUDB是系统核心文件,修改或替换可能导致系统资源统计功能异常,操作前务必备份原文件。

内容的提问来源于stack exchange,提问作者St1nger

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.27 10:15:33