摘点以前写的一个权限管理工具里比较关键的代码,涉及到Windows用户、用户组、权限操作、共享管理。

  • 目录:
    • 1. 遍历用户和组(ShcemaClassName: User, Group, Service)
    • 2. 查找用户、组(查询条件:sid、name、description)
    • 3. 创建用户组
    • 4. 从用户组中添加/删除用户
    • 5. 遍历用户组成员
    • 6. 修改用户密码(ChangePassword: 旧密码,新密码)
    • 7. 重置用户密码(SetPassword: 只提供新密码)
    • 8. 修改/创建用户
    • 9. 创建共享

首先获取顶级DirectoryEntry

   var LocalMachineEntries =
        new System.DirectoryServices.DirectoryEntry(
            "WinNT://" + Environment.MachineName + ",computer");

ActionResult类仅用于保存操作结果,没有特殊东西,老项目里摘的代码,懒得改了。

1. 遍历用户和组(ShcemaClassName: User, Group, Service)


    var LocalMachineEntries =
        new System.DirectoryServices.DirectoryEntry("WinNT://" + Environment.MachineName + ",computer");
    foreach (System.DirectoryServices.DirectoryEntry gentry in LocalMachineEntries.Children)
    {
        string schema = gentry.SchemaClassName;
        string sid = schema.Equals("service", StringComparison.OrdinalIgnoreCase) ?
            "" : BitConverter.ToString((byte[])gentry.InvokeGet("objectSid"));
        Console.WriteLine($"{sid} - {gentry.SchemaClassName} - {gentry.Name}");
    }

2. 查找用户、组(sid、name、description)


/// <summary>
/// 查找用户
/// </summary>
/// <param name="loginname"></param>
/// <param name="DescLimit">是否限定Description查询(是:只查询Description符合要求的用户;否:查询所有系统用户)</param>
/// <param name="uentry"></param>
/// <returns></returns>
public static DirectoryEntry FindUser(string loginname,string desc,  bool descLimit = true)
{
    try
    {
        DirectoryEntry uentry = LocalMachineEntry.Children.Find(loginname, "user");
        if (uentry.InvokeGet("Description").ToString().ToUpper() == desc || !descLimit)
        {
            return uentry;
        }
        else
        {
            return null;
        }
    }
    catch (Exception)
    {
        return null;
    }
}

public static DirectoryEntry FindGroupByName(string groupname,string desc, bool descLimit = true)
{
    try
    {
        DirectoryEntry gentry = LocalMachineEntry.Children.Find(groupname, "group");
        if (gentry.InvokeGet("Description").ToString().ToUpper() == desc || !descLimit)
        {
            return gentry;
        }
        else
        {
            return null;
        }
    }
    catch (Exception)
    {
        return null;
    }
}

public static Group FindGroupBySid(string sid)
{
    try
    {
        foreach (DirectoryEntry gentry in LocalMachineEntry.Children)
        {
            if (gentry.SchemaClassName.ToUpper() == "GROUP" && BitConverter.ToString((byte[])gentry.InvokeGet("objectSid")).ToUpper() == sid)
            {
                if (DicGroups.ContainsKey(gentry.Name))
                {
                    return DicGroups[gentry.Name];
                }
                else
                {
                    Group g = new Group() { Entry = gentry, Name = gentry.Name, Sid = sid, Users = new List<User>() };
                    DicGroups.Add(g.Name, g);
                    return g;
                }
            }
        }
        return null;
    }
    catch (Exception)
    {
        return null;
    }
}

3. 创建用户组


public static DirectoryEntry CreateGroup(string groupname)
{
    DirectoryEntry gEntry = LocalMachineEntry.Children.Add(groupname, "Group");
    gEntry.CommitChanges();
    return gEntry;
}

4. 从用户组中添加/删除用户


public static void SetGroup(string user, string group, DepartmentRole role)
{
    DirectoryEntry userEntry = FindUser(user, "");
    DirectoryEntry gEntry = FindGroupByName(group, "");
    gEntry.Invoke("Add", userEntry.Path);
    gEntry.Invoke("Remove", userEntry.Path);
}

5. 遍历用户组成员

public static IEnumerable GetGroupUsers(string groupname)
{
    DirectoryEntry g = LocalMachineEntry.Children.Find(groupname, "Group");
    return g.Invoke("Members") as IEnumerable;
}

6. 修改用户密码(旧密码,新密码)


public static ActionResult ChangePassword(string loginname, string oldPass, string newPass)
{
    DirectoryEntry ue = FindUser(loginname);
    if (ue is null) return new ActionResult() { Result = false, Message = "修改失败:用户不存在。" };
    try
    {
        object[] password = new object[] { oldPass, newPass };
        object ret = ue.Invoke("ChangePassword", password);
        ue.CommitChanges();
        ue.Close();
        return new ActionResult();
    }
    catch (Exception ex)
    {
        WriteLog("WINFORM", "CHANGEPASSWD", "EXCEPTION", ex.ToString());
        return new ActionResult() { Result = false, Message = $"修改失败:ERR_EX0" };
    }
}

7. 重置用户密码(只提供新密码)


public static ActionResult ResetPassword(string loginname, string newPassword)
{
    try
    {
        DirectoryEntry ue = FindUser(loginname);
        if (ue is null)
        {
            return new ActionResult() { Result = false, Message = "找不到该用户" };
        }
        object ret = ue.Invoke("SetPassword", newPassword);
        ue.CommitChanges();
        ue.Close();
        return new ActionResult();
    }
    catch (Exception ex)
    {
        return new ActionResult() { Result = false, Message = ex.Message };
    }
}

8. 修改/创建用户


/// <summary>
/// 创建/修改用户
/// </summary>
/// <param name="loginname">登录账号</param>
/// <param name="password">密码</param>
/// <param name="group">所在用户组</param>
/// <param name="fullname">全名</param>
/// <returns></returns>
public static ActionResult UpdateUser(string loginname, string password, string group, string fullname = "")
{
    var gEntry = FindGroupByName(group, "", false);

    DirectoryEntry uEntry = null;
    try
    {
        uEntry = FindUser(loginname, "", false);
    }
    catch (Exception)
    {
    }
    if (uEntry is null)
    {//用户不存在时,操作类型为:新建用户
        if (string.IsNullOrEmpty(password)) return new ActionResult() { Message = "创建用户失败,密码不能为空", Result = false };
        uEntry = LocalMachineEntry.Children.Add(loginname, "User");
        uEntry.Properties["FullName"].Add(fullname); //用户全称 
        uEntry.Invoke("SetPassword", password); //用户密码 
        uEntry.InvokeSet("Description", DescriptionFlag);
        uEntry.InvokeSet("UserFlags", PRIV_UNBLOCK);
        try
        {
            uEntry.CommitChanges();
            return new ActionResult() { Message = $"用户{loginname}创建成功。" };
        }
        catch (Exception ex)
        {
            return new ActionResult() { Result = false, Message = $"用户创建失败:\r\n{ex.Message}" };
        }
    }
    else
    {
        //密码参数不为空时才修改密码
        if (!string.IsNullOrEmpty(password)) uEntry.Invoke("SetPassword", password);
        uEntry.InvokeSet("FullName", new object[] { fullname });
        uEntry.InvokeSet("UserFlags", new object[] { PRIV_UNBLOCK });
        uEntry.CommitChanges();
        return new ActionResult() { Message = $"用户{loginname}修改成功。" };
    }
}

9. 创建共享


public static ActionResult CreateShare(string pathroot, string group, string sid)
{
    //NTFS权限
    DirectoryInfo dir = new DirectoryInfo(pathroot);
    DirectorySecurity dirSecurity = new DirectorySecurity();
    InheritanceFlags inherits = InheritanceFlags.ContainerInherit | InheritanceFlags.ObjectInherit;
    FileSystemAccessRule rule1 =//普通权限
        new FileSystemAccessRule(group, FileSystemRights.ReadAndExecute, inherits, PropagationFlags.None, AccessControlType.Allow);
    FileSystemAccessRule rule2 =//所有权限
        new FileSystemAccessRule(group, FileSystemRights.FullControl, inherits, PropagationFlags.None, AccessControlType.Allow);

    //共享权限
    List<string> msg = new List<string>();
    dirSecurity.ModifyAccessRule(AccessControlModification.Add, rule1, out bool res1);
    dirSecurity.ModifyAccessRule(AccessControlModification.Add, rule2, out bool res2);
    dir.SetAccessControl(dirSecurity);

    ManagementObject trustee = new ManagementClass(new ManagementPath("Win32_Trustee"), null);
    trustee["Name"] = group;
    trustee["SID"] = sid;

    //ACE0, ACE1, ACE2对应禁用、普通、管理,按需取用
    ManagementObject ACE0 = new ManagementClass(new ManagementPath("Win32_Ace"), null);//禁用
    ManagementObject ACE1 = new ManagementClass(new ManagementPath("Win32_Ace"), null);//普通
    ManagementObject ACE2 = new ManagementClass(new ManagementPath("Win32_Ace"), null);//管理
    ACE0["AccessMask"] = 2032127;
    ACE0["AceFlags"] = AceFlags.ObjectInherit | AceFlags.ContainerInherit;
    ACE0["AceType"] = AceType.AccessDenied;
    ACE0["Trustee"] = trustee;

    ACE1["AccessMask"] = 1179817;
    ACE1["AceFlags"] = AceFlags.ObjectInherit | AceFlags.ContainerInherit;
    ACE1["AceType"] = AceType.AccessAllowed;
    ACE0["Trustee"] = trustee;

    ACE2["AccessMask"] = 2032127;
    ACE2["AceFlags"] = AceFlags.ObjectInherit | AceFlags.ContainerInherit;
    ACE2["AceType"] = AceType.AccessAllowed;
    ACE0["Trustee"] = trustee;

    ManagementObject secDescriptor = new ManagementClass(new ManagementPath("Win32_SecurityDescriptor"), null);
    secDescriptor["ControlFlags"] = 4;
    secDescriptor["DACL"] = new object[] { ACE0, ACE1, ACE2 };

    ManagementClass managementClass = new ManagementClass("Win32_Share");
    ManagementBaseObject inParams = managementClass.GetMethodParameters("Create");
    ManagementBaseObject outParams;
    inParams["Name"] = group;
    inParams["Description"] = $"{group} 共享目录";
    inParams["Path"] = pathroot;
    inParams["Type"] = 0x0; // Disk Drive
    inParams["Access"] = secDescriptor;
    outParams = managementClass.InvokeMethod("Create", inParams, null);

    if ((uint)(outParams.Properties["ReturnValue"].Value) != 0)
    {
        throw new Exception("创建共享失败");
    }

    if (res1 && res2)
    {
        return new ActionResult();
    }
    else
    {
        return new ActionResult() { Result = false, Message = string.Join("\r\n", msg) };
    }
}