我試着按照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。我們把從內catch
塊RelaunchWithAdministratorRights
爲:
try
{
...
}
catch (SecurityException)
{
RelaunchWithAdministratorRights(args);
return;
}
在我們的應用程序,我們只是調用RelaunchWithAdministratorRights
後返回退出,缺乏權限的應用程序的實例。根據你的應用程序,你可能更喜歡throw
你的出路。無論如何,從RelaunchWithAdministratorRights
返回後,您不希望此實例繼續處理。
享受!
嗯 - 複製權限_and_屬性正是我想要實現的行爲。 - 對不起,我以前沒有告訴過你; ;-) 是的,應用程序可以確保使用管理員帳戶。 – dhh 2010-06-25 14:02:51