代码之家  ›  专栏  ›  技术社区  ›  dhh

如何复制NTFS权限

  •  0
  • dhh  · 技术社区  · 14 年前

    I found a method for copying ntfs permissions information from one existing folder to a newly created one - I'm not sure if it's doing the work it should do. Maybe one can have a look at the method and give some comments:

    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);
    }
    

    谢谢你的帮助, 丹尼尔

    2 回复  |  直到 10 年前
        1
  •  1
  •   Abel    14 年前

    It does slightly more than just copying the NTFS permissions. It also copies the attributes of the file. I'm not quite certain whether it copies inherited permissions, though, but run it once and you should be able to find out.

    Note that copying permissions on and of itself requires special permissions (administrators have these, of course), be sure the process running this method has the required permissions to query, view and set permissions on those objects.

        2
  •  2
  •   Gyle Iverson    10 年前

    I tried following the OP suggested pattern for copying a file's ACLs and attributes and found a few issues in our application. Hopefully this information helps others.

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

    The SetAccessControl method persists only FileSecurity objects that 已在对象创建后修改。如果文件安全对象 尚未修改,它将不会持久化到文件中。因此, it is not possible to retrieve a FileSecurity object from one file and 将同一对象重新应用于其他文件 .

    It is necessary to make a new FileSecurity 目标文件的对象,并将源文件的副本分配给此对象 文件安全性 对象。

    Here is an example of a pattern that works from our app.

        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);
        }
    

    After fixing the first issue, then we found the owner attribute was not being copied. Instead, the destination file was owned by Administrator in our case. To get around that the process needs to enable the SE_RESTORE_NAME privilege. 退房 AdjustTokenPrivileges on pinvoke.net for a complete Privileges class that makes setting privileges easy.

    我们必须处理的最后一件事就是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);
        }
    

    Ours was a console app so we need to pass the args 参数来自 Main 方法到 RelaunchWithAdministratorRights(args) . 非控制台应用程序可以改为传递空值。我们打电话 RelaunchWithAdministratorRights 从内 catch 块如:

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

    In our app we just return after the call to 重新启动具有管理员权限 to exit the instance of the app that lacked privileges. Depending on your app, you may prefer to throw 你的出路。无论如何,从返回后 RelaunchWithAdministratorRights 您不希望此实例继续处理。

    享受!