C# 使用安全/权限设置将文件夹复制到另一个目的地

Posted

技术标签:

【中文标题】C# 使用安全/权限设置将文件夹复制到另一个目的地【英文标题】:C# Copying a Folder to another destination with Security/Permission Settings 【发布时间】:2012-07-17 00:57:00 【问题描述】:

我正在制作一个程序,它可以复制文件夹并将其转移到另一个位置,包括属性、权限、安全设置。

到目前为止,我可以使用 Attribution,但在权限/安全设置方面存在问题。这是我的代码:

Directory.CreateDirectory(Destination);
DirectoryInfo DestAttribute = new DirectoryInfo(Destination);
DestAttribute.Attributes = Source.Attributes; // Copies Attributes from Source to Dest

AuthorizationRuleCollection Rule;
DirectorySecurity DestSecurity = Source.GetAccessControl();
Rule = DestSecurity.GetAccessRules(true, true, typeof(NTAccount));
DestSecurity.AddAccessRule(Rule);
DestAttribute.SetAccessControl(DestSecurity);

任何人对让它工作有什么建议吗? 谢谢大家的帮助。

【问题讨论】:

似乎是重复的? [原始问题...][1] 克里斯 [1]:***.com/questions/9995311/… 【参考方案1】:

基于Chris Keller's答案的递归版本

    /// <summary>
    /// Copy directory recursive with permissions, overwrite existing
    /// </summary>
    /// <param name="sourceFolder"></param>
    /// <param name="destinationFolder"></param>
    public static void CopyDirectory(string sourceFolder, string destinationFolder)
    
        var sourceDirectory = new DirectoryInfo(sourceFolder);
        if (!sourceDirectory.Exists) throw new DirectoryNotFoundException("Source folder not found: " + sourceFolder);

        var destinationDirectory = !Directory.Exists(destinationFolder) ? Directory.CreateDirectory(destinationFolder) : new DirectoryInfo(destinationFolder);

        CopyDirectory(sourceDirectory,destinationDirectory);
    

    public static void CopyDirectory(DirectoryInfo sourceDirectory, DirectoryInfo destinationDirectory)
    
        if(sourceDirectory == null) throw new ArgumentException("sourceDirectory");
        if(destinationDirectory == null) throw new ArgumentException("destinationDirectory");

        var security = sourceDirectory.GetAccessControl();

        security.SetAccessRuleProtection(true, true);
        destinationDirectory.SetAccessControl(security);

        var dirsToCopy = sourceDirectory.GetDirectories();
        foreach (var dirToCopy in dirsToCopy)
        
            var destSubDirPath = Path.Combine(destinationDirectory.FullName,dirToCopy.Name);
            var destinationSubDir = !Directory.Exists(destSubDirPath) ? Directory.CreateDirectory(destSubDirPath) : new DirectoryInfo(destSubDirPath);
            CopyDirectory(dirToCopy,destinationSubDir);
        

        var filesToCopy = sourceDirectory.GetFiles();

        foreach (var file in filesToCopy)
        
            CopyFile(file, destinationDirectory.FullName);
        
    

    private static void CopyFile(FileInfo file, string destinationDirectory)
    
        var path = Path.Combine(destinationDirectory, file.Name);
        var fileSecurity = file.GetAccessControl();

        fileSecurity.SetAccessRuleProtection(true, true);

        file.CopyTo(path, true);

        var copiedFile = new FileInfo(path);

        copiedFile.SetAccessControl(fileSecurity);
    

【讨论】:

【参考方案2】:

MSDN: How To copy ACL information from one file to another

SetAccessControl 方法仅保留在对象创建后已修改的 DirectorySecurity 对象。如果未修改 DirectorySecurity 对象,则不会将其保存到文件中。因此,不可能从一个文件中检索 DirectorySecurity 对象并将同一对象重新应用到另一个文件。

将 ACL 信息从一个文件复制到另一个文件:

    使用 GetAccessControl 方法从源文件中检索 DirectorySecurity 对象。

    为目标文件创建一个新的 DirectorySecurity 对象。

    使用 GetSecurityDescriptorBinaryForm 或 GetSecurityDescriptorSddlForm 方法 源 DirectorySecurity 对象来检索 ACL 信息。

    使用 SetSecurityDescriptorBinaryForm 或 SetSecurityDescriptorSddlForm 方法将步骤 3 中检索到的信息复制到目标 DirectorySecurity 对象。

    使用 SetAccessControl 方法将目标 DirectorySecurity 对象设置为目标文件。

例子:

DirectoryInfo dir1 = new DirectoryInfo(@"C:\Temp\Dir1");
DirectoryInfo dir2 = new DirectoryInfo(@"C:\Temp\Dir2");  


DirectorySecurity ds1 = dir1.GetAccessControl();
DirectorySecurity ds2 = new DirectorySecurity();
ds2.SetSecurityDescriptorBinaryForm(ds1.GetSecurityDescriptorBinaryForm());
dir2.SetAccessControl(ds2);

【讨论】:

【参考方案3】:

过了一会儿,我终于想出了如何让它工作。 目标是:从一个文件夹(不是文件)复制权限,并将其转移到另一个文件夹。 (权限:账号设置、访问规则等...)

我就是这样做的:(帮助来自:http://forums.asp.net/t/1390009.aspx/1)

    private void PermissionGet(DirectoryInfo Source, DirectoryInfo Destination)
    
        string Username;
        DirectorySecurity SourceSecurity = Source.GetAccessControl();

        foreach (FileSystemAccessRule Rules in SourceSecurity.GetAccessRules(true, true, typeof(System.Security.Principal.NTAccount)))
        
            Username = Rules.IdentityReference.Value;
            PermissionSet(Username, Rules.FileSystemRights, Rules.AccessControlType, Destination);
        
    

    private void PermissionSet(string Username, FileSystemRights Permission, AccessControlType Access, DirectoryInfo Destination)
    
        DirectorySecurity Security = Destination.GetAccessControl();
        Security.AddAccessRule(new FileSystemAccessRule(Username, Permission, Access));
        Destination.SetAccessControl(Security);
    

【讨论】:

【参考方案4】:

这似乎与以下内容重复:

Original Question...

(来自原始问题的代码示例)

FileInfo file1 = new FileInfo(@"c:\test.txt");
FileInfo file2 = new FileInfo(@"c:\test2.txt");
StreamReader sr1 = new StreamReader(file1.Open(FileMode.Open));
StreamWriter sw1 = new StreamWriter(file2.Open(FileMode.Create));
sw1.Write(sr1.ReadToEnd());
sr1.Close();
sw1.Close();
FileSecurity ac1 = file1.GetAccessControl();
ac1.SetAccessRuleProtection(true, true);
file2.SetAccessControl(ac1);

我将以下方法放在一起,它似乎可以满足您的需求......

private static void FolderCopy(String sourceFolder, String destinationFolder)

    DirectoryInfo sourceDirectory = new DirectoryInfo(sourceFolder);
    DirectoryInfo destinationDirectory;

    if (!sourceDirectory.Exists)
    
        throw new DirectoryNotFoundException("Source folder not found: " + sourceFolder);
    

    if (!Directory.Exists(destinationFolder))
    
        destinationDirectory = Directory.CreateDirectory(destinationFolder);
    
    else
    
        destinationDirectory = new DirectoryInfo(destinationFolder);
    

    DirectorySecurity security = sourceDirectory.GetAccessControl();

    security.SetAccessRuleProtection(true, true);
    destinationDirectory.SetAccessControl(security);

    var filesToCopy = sourceDirectory.GetFiles();

    foreach (FileInfo file in filesToCopy)
    
        String path = Path.Combine(destinationFolder, file.Name);
        FileSecurity fileSecurity = file.GetAccessControl();

        fileSecurity.SetAccessRuleProtection(true, true);

        file.CopyTo(path, false);

        FileInfo copiedFile = new FileInfo(path);

        copiedFile.SetAccessControl(fileSecurity);
    

克里斯

【讨论】:

您好,如果您觉得这是重复的,我很抱歉。该方法适用于文件,我尝试将其转换为目录版本,但运气不佳。在发表这篇文章之前,我还查看了该主题以及所有其他链接。遗憾的是,错误仍然存​​在。 我刚刚在我的原始答案中添加了一个示例方法。也许有了它和您的原始代码,您就可以完成您的任务。 哇,非常感谢!我不敢相信就是这么简单的“AccessRuleProtection”。你的代码和我的一样,但只有两行(:干得好! 伙计,这救了我的命。我添加了代码以递归地复制文件夹 - 但是,我没有创建子文件夹的权限,所以我不得不强制添加一个新的访问规则来让当前用户完全控制这样做。

以上是关于C# 使用安全/权限设置将文件夹复制到另一个目的地的主要内容,如果未能解决你的问题,请参考以下文章

如何将一个文件夹复制到另一个文件夹中并保留其权限

以编程方式向 C# 中的文件添加安全权限

C# 使用其他域/用户名/密码将文件复制到另一个目录

将文件复制到另一个文件夹,在目的地重命名并覆盖现有文件

C# 将文件夹中文件复制到另一个文件夹

如何将具有属性/权限的目录从一个位置复制到另一个位置?