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

ZipFile解压高权限目录抛System.UnauthorizedAccessException求助

解压高权限文件夹时的权限异常解决方案

尝试将文件解压到C:\ProgramData\Tecan这类高权限目录时,持续触发UnauthorizedAccessException,目标是无需批量修改每台计算机的外部权限即可解决问题。

异常信息

System.Exception: Error transferring files
---> System.Exception: Error unzipping C:\TransferFiles\ZipFolder.zip to C:\ProgramData\Tecan
---> System.UnauthorizedAccessException: Access to the path C:\ProgramData\Tecan\SVNRoot\SystemSW_1.0\format is denied.
at Microsoft.Win32.SafeHandles.SafeFileHandle.CreateFile(String fullPath, FileMode mode, FileAccess access, FileShare share, FileOptions options)
at Microsoft.Win32.SafeHandles.SafeFileHandle.Open(String fullPath, FileMode mode, FileAccess access, FileShare share, FileOptions options, Int64 preallocationSize, Nullable1 unixCreateMode)
at System.IO.Strategies.OSFileStreamStrategy..ctor(String path, FileMode mode, FileAccess access, FileShare share, FileOptions options, Int64 preallocationSize, Nullable1 unixCreateMode)
at System.IO.Strategies.FileStreamHelpers.ChooseStrategyCore(String path, FileMode mode, FileAccess access, FileShare share, FileOptions options, Int64 preallocationSize, Nullable`1 unixCreateMode)
at System.IO.FileStream..ctor(String path, FileStreamOptions options)
at System.IO.Compression.ZipFileExtensions.ExtractToFile(ZipArchiveEntry source, String destinationFileName, Boolean overwrite)
at System.IO.Compression.ZipFileExtensions.ExtractRelativeToDirectory(ZipArchiveEntry source, String destinationDirectoryName, Boolean overwrite)
at System.IO.Compression.ZipFileExtensions.ExtractToDirectory(ZipArchive source, String destinationDirectoryName, Boolean overwriteFiles)
at System.IO.Compression.ZipFile.ExtractToDirectory(String sourceArchiveFileName, String destinationDirectoryName, Encoding entryNameEncoding, Boolean overwriteFiles)

已尝试操作

  • 以管理员身份运行Visual Studio Code及程序,解决了其他权限问题,但未解决本次解压异常
  • 怀疑无扩展名文件导致,但此类文件可正常解压到低权限目录
  • 尝试通过C#代码修改目标目录的访问规则和所有者:

修改目录访问规则代码

DirectoryInfo directoryInfo = new DirectoryInfo(destination);
DirectorySecurity directorySecurity = directoryInfo.GetAccessControl();

FileSystemAccessRule fileSystemAccessRule = new FileSystemAccessRule
(
    new SecurityIdentifier(WellKnownSidType.BuiltinAdministratorsSid, null),
    FileSystemRights.FullControl,
    InheritanceFlags.ContainerInherit | InheritanceFlags.ObjectInherit,
    PropagationFlags.InheritOnly,
    AccessControlType.Allow
);

directorySecurity.AddAccessRule(fileSystemAccessRule);
directoryInfo.SetAccessControl(directorySecurity);

修改目录所有者代码

DirectoryInfo directoryInfo = new DirectoryInfo(destination);
DirectorySecurity directorySecurity = directoryInfo.GetAccessControl();

var owner = directorySecurity.GetOwner(typeof(NTAccount));
var newOwner = new NTAccount(WindowsIdentity.GetCurrent().Name);

directorySecurity.SetOwner(newOwner);
directoryInfo.SetAccessControl(directorySecurity);

可行解决方案

1. 先解压到临时目录再移动文件

先将ZIP包解压到用户权限可读写的临时目录(如C:\Users\[当前用户]\AppData\Local\Temp),再以管理员权限将文件移动到目标高权限目录。移动操作的权限检查逻辑与直接解压不同,更容易绕过目录权限限制。

示例代码:

string tempDir = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString());
ZipFile.ExtractToDirectory("C:\\TransferFiles\\ZipFolder.zip", tempDir);

// 递归移动所有文件到目标目录
foreach (var file in Directory.GetFiles(tempDir, "*", SearchOption.AllDirectories))
{
    string relativePath = Path.GetRelativePath(tempDir, file);
    string destPath = Path.Combine("C:\\ProgramData\\Tecan", relativePath);
    
    // 创建目标父目录(如果不存在)
    Directory.CreateDirectory(Path.GetDirectoryName(destPath));
    // 覆盖已存在的文件
    File.Move(file, destPath, overwrite: true);
}

// 清理临时目录
Directory.Delete(tempDir, recursive: true);

2. 使用Windows Shell API执行文件操作

Windows的SHFileOperation或IFileOperationAPI原生支持权限提升逻辑,比.NET自带的文件操作更适配Windows权限模型。通过P/Invoke调用SHFileOperation实现文件复制:

示例代码:

using System.Runtime.InteropServices;

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
public struct SHFILEOPSTRUCT
{
    public IntPtr hwnd;
    public uint wFunc;
    public string pFrom;
    public string pTo;
    public ushort fFlags;
    public bool fAnyOperationsAborted;
    public IntPtr hNameMappings;
    public string lpszProgressTitle;
}

[DllImport("shell32.dll", CharSet = CharSet.Unicode)]
public static extern int SHFileOperation(ref SHFILEOPSTRUCT lpFileOp);

// 使用示例
string tempDir = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString());
ZipFile.ExtractToDirectory("C:\\TransferFiles\\ZipFolder.zip", tempDir);

var fileOp = new SHFILEOPSTRUCT
{
    wFunc = 0x0002, // FO_COPY:执行复制操作
    pFrom = tempDir + "\0\0", // 路径需以双NULL结尾
    pTo = "C:\\ProgramData\\Tecan\0\0",
    fFlags = 0x0040 | 0x0008 // FOF_NOCONFIRMATION(不弹出确认框)| FOF_SILENT(静默执行)
};

SHFileOperation(ref fileOp);

// 清理临时目录
Directory.Delete(tempDir, recursive: true);

3. 逐个解压并手动设置文件权限

放弃使用ZipFile.ExtractToDirectory的批量解压,改为逐个处理ZIP条目,在创建文件/目录后立即为当前用户添加全控制权限,避免继承目标目录的受限权限。

示例代码:

using (var archive = ZipFile.OpenRead("C:\\TransferFiles\\ZipFolder.zip"))
{
    foreach (var entry in archive.Entries)
    {
        string destPath = Path.Combine("C:\\ProgramData\\Tecan", entry.FullName);
        
        if (entry.FullName.EndsWith("/"))
        {
            // 处理目录
            Directory.CreateDirectory(destPath);
            var dirInfo = new DirectoryInfo(destPath);
            var dirSec = dirInfo.GetAccessControl();
            
            // 为当前用户添加全控制权限
            dirSec.AddAccessRule(new FileSystemAccessRule(
                WindowsIdentity.GetCurrent().User,
                FileSystemRights.FullControl,
                InheritanceFlags.ContainerInherit | InheritanceFlags.ObjectInherit,
                PropagationFlags.None,
                AccessControlType.Allow));
            
            dirInfo.SetAccessControl(dirSec);
        }
        else
        {
            // 处理文件
            Directory.CreateDirectory(Path.GetDirectoryName(destPath));
            
            // 写入文件
            using (var fs = new FileStream(destPath, FileMode.Create, FileAccess.Write, FileShare.None))
            using (var entryStream = entry.Open())
            {
                entryStream.CopyTo(fs);
            }
            
            // 为当前用户添加文件全控制权限
            var fileInfo = new FileInfo(destPath);
            var fileSec = fileInfo.GetAccessControl();
            
            fileSec.AddAccessRule(new FileSystemAccessRule(
                WindowsIdentity.GetCurrent().User,
                FileSystemRights.FullControl,
                AccessControlType.Allow));
            
            fileInfo.SetAccessControl(fileSec);
        }
    }
}

内容的提问来源于stack exchange,提问作者Ricardo Noyola Lozano

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.15 13:11:02