2010-06-25 112 views
0

我发现了一种将ntfs权限信息从一个现有文件夹复制到新创建的文件夹的方法 - 我不确定它是否正在执行它应该执行的工作。也许我们可以看看该方法并给出一些意见:如何复制ntfs权限

private static void CopySecurityInformation(String source, String dest) 
{ 
    FileSecurity fileSecurity = File.GetAccessControl(
     source, 
     AccessControlSections.All); 
    FileAttributes fileAttributes = File.GetAttributes(source); 
    File.SetAccessControl(dest, fileSecurity); 
    File.SetAttributes(dest, fileAttributes); 
} 

感谢您的帮助, 丹尼尔

回答

1

这并不仅仅是复制的NTFS权限稍多。它还复制文件的属性。不过,我不太确定它是否复制继承权限,但是运行一次,您应该能够找出答案。

请注意,复制权限本身需要特殊权限(管理员当然有这些权限),请确保运行此方法的进程具有查询,查看和设置这些对象权限所需的权限。

+0

嗯 - 复制权限_and_属性正是我想要实现的行为。 - 对不起,我以前没有告诉过你; ;-) 是的,应用程序可以确保使用管理员帐户。 – dhh 2010-06-25 14:02:51

2

我试着按照OP建议的模式来复制文件的ACL和属性,并在我们的应用程序中发现了一些问题。希望这些信息可以帮助其他人。

根据MSDN,使用上述File.SetAccessControl()方法将不起作用。

SetAccessControl方法在对象创建后仅保留 已被修改的FileSecurity对象。如果FileSecurity对象 尚未修改,则它不会被持久保存到文件中。因此, 无法从一个文件检索FileSecurity对象,并且 将同一对象重新应用到另一个文件

有必要为目标文件制作一个新的FileSecurity对象,并为其分配一个源FileSecurity对象的副本。

这里是一个模式的例子,从我们的应用程序工作。

public static void CopyFile(string source, string destination) 
    { 
     // Copy the file 
     File.Copy(source, destination, true); 

     // Get the source file's ACLs 
     FileSecurity fileSecuritySource = File.GetAccessControl(source, AccessControlSections.All); 
     string sddlSource = fileSecuritySource.GetSecurityDescriptorSddlForm(AccessControlSections.All); 

     // Create the destination file's ACLs 
     FileSecurity fileSecurityDestination = new FileSecurity(); 
     fileSecurityDestination.SetSecurityDescriptorSddlForm(sddlSource); 

     // Set the destination file's ACLs 
     File.SetAccessControl(destination, fileSecurityDestination); 

     // copy the file attributes now 
     FileAttributes fileAttributes = File.GetAttributes(source); 
     File.SetAttributes(destination, fileAttributes); 
    } 

修复第一个问题后,我们发现所有者属性未被复制。相反,在我们的例子中,目标文件由Administrator拥有。为了避免该进程需要启用SE_RESTORE_NAME特权。在pinvoke.net上查看AdjustTokenPrivileges,获取完整的权限类,使设置权限变得轻松。我们不得不处理的最后一件事是UAC。如果用户在UAC下运行,我们需要使用管理权限重新启动我们的应用程序。这里是我们的应用程序的另一个例子,它涉及用提升的特权重新启动应用程序。

private static void RelaunchWithAdministratorRights(string[] args) 
    { 
     // Launch as administrator 
     ProcessStartInfo processStartInfo = new ProcessStartInfo(); 
     processStartInfo.UseShellExecute = true; 
     processStartInfo.WorkingDirectory = Environment.CurrentDirectory; 
     string executablePath = System.Reflection.Assembly.GetExecutingAssembly().Location; 
     processStartInfo.FileName = executablePath; 
     processStartInfo.Verb = "runas"; 

     if (args != null && args.Count() > 0) 
     { 
      string arguments = args[0]; 
      for (int i = 1; i < args.Count(); i++) 
       arguments += " " + args[i]; 
      processStartInfo.Arguments = arguments; 
     } 

     try 
     { 
      using (Process exeProcess = Process.Start(processStartInfo)) 
      { 
       exeProcess.WaitForExit(); 
      } 
     } 
     catch 
     { 
      // The user refused to allow privileges elevation. Do nothing and return directly ... 
     } 

     Environment.Exit(0); 
    } 

我们是一个控制台应用程序,所以我们需要从Main方法将RelaunchWithAdministratorRights(args)传递args参数。非控制台应用程序可以传递null。我们把从内catchRelaunchWithAdministratorRights为:

 try 
     { 
      ... 
     } 
     catch (SecurityException) 
     { 
      RelaunchWithAdministratorRights(args); 
      return; 
     } 

在我们的应用程序,我们只是调用RelaunchWithAdministratorRights后返回退出,缺乏权限的应用程序的实例。根据你的应用程序,你可能更喜欢throw你的出路。无论如何,从RelaunchWithAdministratorRights返回后,您不希望此实例继续处理。

享受!

+0

非常古老的问题 - 但很多谢谢Gyle分享你自己的结果。 – dhh 2014-12-06 23:03:26