我试着按照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