C#使用DirectorySecurity的SetOwner设置文件夹所有者只能设为当前用户

看到有人问了这个问题,查询并实验后发现确实有这个问题,测试代码如下:

static void Main(string[] args)
{
    try
    {
        string folderPath = @"e:\testSecurity";

        Directory.CreateDirectory(folderPath);

        DirectorySecurity defaultFSec = Directory.GetAccessControl(folderPath);

        IdentityReference newUser = new NTAccount("User2");

        defaultFSec.SetOwner(newUser);

        Directory.SetAccessControl(folderPath, defaultFSec);
    }
    catch(Exception ex)
    {
        Console.WriteLine(ex);
    }
    Console.ReadLine();
}

结果是System.InvalidOperationException: The security identifier is not allowed to be the owner of this object.

2005年在Microsoft Connect上就有人提出了这个问题,微软说下个版本将会考虑添加这个功能,然而现在似乎还不行。

当然总是有什么其他办法的,既然资源管理器可以做到,那么直接调用API就是一个可行的办法。Richard Willis给出了一个实现方法,我这里把他的代码转贴一下:

sealed class UnmanagedCode
{
    [DllImport("kernel32.dll", SetLastError=true)]
    [return: MarshalAs(UnmanagedType.Bool)]
    static extern bool CloseHandle(IntPtr hObject);

    // Use this signature if you do not want the previous state
    [DllImport("advapi32.dll", SetLastError=true)]
    [return: MarshalAs(UnmanagedType.Bool)]
    static extern bool AdjustTokenPrivileges(IntPtr tokenHandle,
        [MarshalAs(UnmanagedType.Bool)]bool disableAllPrivileges,
        ref TOKEN_PRIVILEGES newState,
        UInt32 bufferLength,
        IntPtr previousState,
        IntPtr returnLength);

    [DllImport("kernel32.dll", ExactSpelling = true)]
    static extern IntPtr GetCurrentProcess();

    [DllImport("advapi32.dll", ExactSpelling = true, SetLastError = true)]
    static extern bool OpenProcessToken
        (IntPtr processHandle, int desiredAccess, ref IntPtr phtok);

    [DllImport("advapi32.dll", SetLastError = true)]
    static extern bool LookupPrivilegeValue
            (string host, string name, ref LUID lpLuid);

    [StructLayout(LayoutKind.Sequential, Pack = 1)]
    struct TOKEN_PRIVILEGES
    {
        public UInt32 PrivilegeCount;
        public LUID Luid;
        public UInt32 Attributes;
    }

    [StructLayout(LayoutKind.Sequential)]
    public struct LUID
    {
       public uint LowPart;
       public int HighPart;
    }

    const int SE_PRIVILEGE_ENABLED = 0x00000002;
    const int TOKEN_QUERY = 0x00000008;
    const int TOKEN_ADJUST_PRIVILEGES = 0x00000020;
    //http://msdn.microsoft.com/en-us/library/bb530716(VS.85).aspx
    const string SE_RESTORE_PRIVILEGE = "SeRestorePrivilege"; 

    public static void GiveRestorePrivilege()
    {
        TOKEN_PRIVILEGES tokenPrivileges;
        tokenPrivileges.PrivilegeCount = 1;
        tokenPrivileges.Luid = new LUID();
        tokenPrivileges.Attributes = SE_PRIVILEGE_ENABLED;

        IntPtr tokenHandle = RetrieveProcessToken();

        try
        {
            bool success = LookupPrivilegeValue
                        (null, SE_RESTORE_PRIVILEGE, ref tokenPrivileges.Luid);
            if (success == false)
            {
                int lastError = Marshal.GetLastWin32Error();
                throw new Exception(
                    string.Format("Could not find privilege {0}. Error {1}",
                                        SE_RESTORE_PRIVILEGE, lastError));
            }

            success = AdjustTokenPrivileges(
                                                tokenHandle, false,
                                                ref tokenPrivileges, 0,
                                                IntPtr.Zero, IntPtr.Zero);
            if (success == false)
            {
                int lastError = Marshal.GetLastWin32Error();
                throw new Exception(
                    string.Format("Could not assign privilege {0}. Error {1}",
                                    SE_RESTORE_PRIVILEGE, lastError));
            }
        }
        finally
        {
            CloseHandle(tokenHandle);
        }

    }

    static IntPtr RetrieveProcessToken()
    {
        IntPtr processHandle = GetCurrentProcess();
        IntPtr tokenHandle = IntPtr.Zero;
        bool success = OpenProcessToken(processHandle,
                                        TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
                                        ref tokenHandle);
        if (success == false)
        {
            int lastError = Marshal.GetLastWin32Error();
            throw new Exception(
                string.Format("Could not retrieve process token. Error {0}",
                                    lastError));
        }
        return tokenHandle;
    }
}

转载于:https://www.cnblogs.com/Gildor/archive/2010/06/30/1767982.html

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
C#设置文件夹的访问权限可以通过 System.IO 命名空间中的 Directory 类实现。具体步骤如下: 1. 引入 System.IO 命名空间。 2. 使用 Directory 类的 Create 方法创建文件夹。 3. 使用 Directory 类的 GetAccessControl 方法获取文件夹的访问控制列表(ACL)。 4. 使用 FileSystemAccessRule 类创建一个新的访问规则,并指定要授予的用户或组、访问权限和访问控制类型。 5. 使用 DirectorySecurity 类的 AddAccessRule 方法将访问规则添加到文件夹的 ACL 中。 6. 使用 Directory 类的 SetAccessControl 方法将更新后的 ACL 应用到文件夹中。 下面是一个设置文件夹允许访问的示例代码: ```csharp using System.IO; using System.Security.AccessControl; string folderPath = @"C:\Temp"; Directory.CreateDirectory(folderPath); DirectoryInfo directoryInfo = new DirectoryInfo(folderPath); DirectorySecurity directorySecurity = directoryInfo.GetAccessControl(); string user = Environment.UserDomainName + "\\" + Environment.UserName; FileSystemAccessRule rule = new FileSystemAccessRule( user, FileSystemRights.ReadAndExecute, InheritanceFlags.ContainerInherit | InheritanceFlags.ObjectInherit, PropagationFlags.None, AccessControlType.Allow); directorySecurity.AddAccessRule(rule); directoryInfo.SetAccessControl(directorySecurity); ``` 上面的代码将在 C 盘根目录下创建一个名为 Temp 的文件夹,并将其权限设置为允许当前用户读取和执行文件夹中的文件。在添加访问规则时,使用了 InheritanceFlags 和 PropagationFlags 参数指定了继承和传播规则,以确保访问权限应用到文件夹及其子文件夹和文件上。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值