2010-06-25 113 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