65.9K
CodeProject 正在变化。 阅读更多。
Home

Windows 下重置用户访问权限

starIconstarIconstarIconstarIconstarIcon

5.00/5 (1投票)

2017年8月14日

CPOL

1分钟阅读

viewsIcon

7317

downloadIcon

139

一个重置 Windows 用户访问权限的命令行程序

引言

自从 Windows Vista 引入用户帐户控制 (UAC) 以来,对某些系统文件夹的访问受到了限制。除非具有管理员权限,否则不允许修改这些文件夹。虽然 UAC 对于安全性至关重要,但在某些情况下,我们希望授予用户对某些文件夹的完全访问权限(例如 C:\ProgramData\[CompanyName]\[AppName],尽管微软不推荐这样做)。这个简单的命令行程序旨在处理这个问题。

详细说明

要重置访问权限,首先,我们需要确保程序始终以管理员身份运行。这可以通过添加应用程序清单文件来实现,并在其中添加 <requestedExecutionLevel level="requireAdministrator" uiAccess="false" />,如评论 UAC Manifest Options 中所述。

接下来,我们需要确保访问权限被文件夹中所有子文件夹和文件正确继承。这是通过 TraverseDirectorySetFileInheritanceSetDirectoryInheritance 方法完成的。

最后,让我们检查 SetDirectoryAccess 方法。请注意,我们使用 InheritanceFlags.ContainerInherit | InheritanceFlags.ObjectInheritPropagationFlags.None,因为我们希望我们的访问规则不仅应用于此文件夹,还应用于子文件夹和文件。这篇文章解释了我们的访问规则范围与相应标志之间的关系。

?using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Security.AccessControl;
using System.Security.Principal;
using System.Text;
using System.Threading.Tasks;

namespace PermitAccess
{
    class Program
    {
        static void Main(string[] args)
        {
            foreach (var arg in args)
            {
                var success = ResetDirectory(arg);

                var msg = success ?
                    string.Format("Access permission has been reset for 
                                   all subfolders and files in directory {0}", arg) :
                    string.Format("Unable to reset access permission for directory {0}", arg);
                
                Console.WriteLine(msg);
            }

            Console.WriteLine("Press any key to continue...");
            Console.ReadKey();
        }

        public static bool ResetDirectory(string path)
        {
            bool accessSet = false;

            try
            {
                if (!Directory.Exists(path))
                {
                    Directory.CreateDirectory(path);
                }

                TraverseDirectory(path);

                accessSet = SetDirectoryAccess(path);
            }
            catch (IOException ex)
            {
                Console.WriteLine("An unexpected exception just occurred. Details:");
                Console.WriteLine(ex.Message);

                return false;
            }

            return accessSet;
        }

        private static void TraverseDirectory(string path)
        {
            // First set inheritance for the dir itself
            SetDirectoryInheritance(path);

            var files = Directory.GetFiles(path);

            foreach (var f in files)
            {
                // Then set inheritance for each file in this dir
                SetFileInheritance(f);
            }

            var directories = Directory.GetDirectories(path);

            foreach (var d in directories)
            {
                // Recursively call this method
                TraverseDirectory(d);
            }
        }

        private static void SetFileInheritance(string path)
        {
            var fileInfo = new FileInfo(path);
            var fileSecurity = fileInfo.GetAccessControl();
            fileSecurity.SetAccessRuleProtection(false, true);
            fileInfo.SetAccessControl(fileSecurity);
        }

        private static void SetDirectoryInheritance(string path)
        {
            var directoryInfo = new DirectoryInfo(path);
            var directorySecurity = directoryInfo.GetAccessControl();
            directorySecurity.SetAccessRuleProtection(false, true);
            directoryInfo.SetAccessControl(directorySecurity);
        }

        private static bool SetDirectoryAccess(string path)
        {
            var directoryInfo = new DirectoryInfo(path);
            var directorySecurity = directoryInfo.GetAccessControl();
            var securityIdentifier = new SecurityIdentifier
                (WellKnownSidType.BuiltinUsersSid,
                null);
            var rule = new FileSystemAccessRule(
                    securityIdentifier,
                    FileSystemRights.FullControl,
                    InheritanceFlags.ContainerInherit |
                    InheritanceFlags.ObjectInherit,
                    PropagationFlags.None,
                    AccessControlType.Allow);
            bool modified;

            directorySecurity.ModifyAccessRule(AccessControlModification.Add, rule, out modified);
            directoryInfo.SetAccessControl(directorySecurity);

            return modified;
        }
    }
}

Using the Code

要使用此代码,您可以首先构建此项目,并将 PermitAccess.exe 复制到您自己程序的输出文件夹中。在您的程序中,调用

Process uacProcess = new Process();
uacProcess.StartInfo.FileName = "PermitAccess.exe";
uacProcess.StartInfo.Arguments = @"[Directory to reset]";
uacProcess.Start();

请注意,您不需要强制您的程序以管理员身份运行。PermitAccess.exe 本身会要求用户提供管理员权限。

您也可以在 Windows 命令提示符中运行 PermitAccess.exe。导航到 PermitAccess.exe 所在的文件夹,并调用 PermitAccess [要重置的目录]

历史

  • 版本 1.0。2017 年 7 月 30 日
© . All rights reserved.