C#으로 Windows 계정 추가 및 삭제

안녕하세요. 언제나휴일입니다.

이번에 다룰 내용은 C#으로 Windows 계정 추가 및 삭제하기 입니다.

Windows Forms 앱(.NET Framework) 프로그램으로 제작하며 앞에서 작성한 WrapNativeLib를 참조합니다.

1. 프로그램 소개 및 컨트롤 배치

먼저 프로그램의 동작을 소개하고 컨트롤을 배치합시다.

MainForm 컨트롤 배치
MainForm 컨트롤 배치

프로그램은 시작하면서 사용자 목록을 리스트 박스(lbox_user)에 보여줍니다.

그룹 목록 또한 리스트 박스(lbox_group)에 보여줍니다.

그룹 목록에 선택한 그룹 내 멤버 목록도 리스트 박스(lbox_gr_user)에 보여줍니다.

또한 선택한 그룹은 Label(lb_gname)에도 선택한 그룹 이름을 보여줍니다.

그룹 내 멤버 목록 리스트 박스에서 선택한 계정 이름을 텍스트 박스(tbox_sel_uname)에 보여줍니다.

사용자가 계정 추가 버튼(btn_add_suer)를 누르면 텍스트 박스(tbox_username)에 입력한 이름의 계정을 추가합니다.

추가한 계정은 선택한 그룹에 속합니다.

만약 계정 삭제 버튼(btn_remove_user)를 누르면 텍스트 박스(tbox_sel_uname)에 Text에 해당하는 계정을 삭제합니다.

2. MainForm 구현

디폴트로 제공한 Form1을 MainForm으로 이름 바꾸기를 수행할게요.

2.1 MainForm의 Load 이벤트 핸들러

먼저 MainForm의 Load 이벤트 핸들러를 추가합니다.

MainForm의 Load 이벤트 핸들러에서는 사용자 목록과 그룹 목록을 얻어와서 리스트 상자에 바인딩 합니다.

        private void MainForm_Load(object sender, EventArgs e)
        {
            lbox_user.DataSource = WrapNative.GetUserNames();
            lbox_group.DataSource = WrapNative.GetGroupNames();

        }

2.2 그룹 목록(lbox_group)의 항목 변경 이벤트 핸들러

그룹 목록(lbox_group)에서 항목 변경 이벤트 핸들러를 추가합니다.

그룹 목록(lbox_group)에서 항목 변경 이벤트 핸들러에서는 선택한 그룹 이름으로 Label(lb_gname)의 Text 속성을 설정합니다.

그리고 그룹 내 항목 멤버 목록(lbox_gr_user)을 데이터 바인딩 합니다.

        private void lbox_group_SelectedIndexChanged(object sender, EventArgs e)
        {
            string gname = string.Empty;
            if(lbox_group.SelectedIndex == -1)
            {
                return;
            }
            gname = lbox_group.SelectedItem.ToString();
            lb_gname.Text = gname;
            lbox_gr_user.DataSource = WrapNative.GetLocalGroupMembers(null, gname);

        }

2.3 계정 추가 버튼(btn_add)의 클릭 이벤트 핸들러

계정 추가 버튼(btn_add)의 클릭 이벤트 핸들러를 추가합니다.

계정 추가 버튼(btn_add)의 클릭 이벤트 핸들러에서는 계정을 추가합니다.

계정을 추가할 때 DirectoryEntry 개체를 이용합니다.

“WinNT://[머신 이름], computer” 경로가 계정 Active Directory입니다.

            DirectoryEntry AD = new DirectoryEntry("WinNT://" +
                Environment.MachineName + ",computer");

여기에 자식으로 계정을 추가합니다.

앞에서 생성한 DirectoryEntry 개체의 자식으로 추가합니다. 이 때 계정 이름과 계정 유형(“user”)을 전달하고 DirectoryEntry 개체를 반환 받습니다.

받환 받은 DirectoryEntry 개체에 Invoke 메서드에 “Put” 행위와 계정 설명을 전달합니다.

그리고 설정한 내용을 확정하기 위해 CommitChanges 메서드를 호출합니다.

            DirectoryEntry new_user = AD.Children.Add(uname, "user");
            new_user.Invoke("Put", new object[] {"Description","WRU"});
            new_user.CommitChanges();

그리고 선택한 그룹 계정을 찾아 DirectoryEntry 개체를 반환 받습니다.

그룹 DirectoryEntry 개체의 Invoke 메서드에 “Add”행위와 추가한 계정 경로를 인자로 전달합니다.

            string gname = "Guests";
            if (lbox_group.SelectedIndex != -1)
            {
                gname = lbox_group.SelectedItem.ToString();
            }

            DirectoryEntry grp = AD.Children.Find(gname, "group");
            if (grp != null)
            {
                grp.Invoke("Add", new object[] { new_user.Path.ToString() });
            }

추가한 내용에 맞게 사용자 목록과 선택한 그룹 내 멤버 목록을 갱신합니다.

            tbox_username.Text = string.Empty;
            lbox_gr_user.DataSource = WrapNative.GetLocalGroupMembers(null, gname);
            lbox_user.DataSource = WrapNative.GetUserNames();

다음은 계정 추가 버튼 클릭 이벤트 핸들러 전체 코드입니다.

        private void btn_add_user_Click(object sender, EventArgs e)
        {
            string uname = tbox_username.Text;
            DirectoryEntry AD = new DirectoryEntry("WinNT://" +
                Environment.MachineName + ",computer");
            DirectoryEntry new_user = AD.Children.Add(uname, "user");
            new_user.Invoke("Put", new object[] {"Description","WRU"});
            new_user.CommitChanges();
            string gname = "Guests";
            if (lbox_group.SelectedIndex != -1)
            {
                gname = lbox_group.SelectedItem.ToString();
            }

            DirectoryEntry grp = AD.Children.Find(gname, "group");
            if (grp != null)
            {
                grp.Invoke("Add", new object[] { new_user.Path.ToString() });
            }
            tbox_username.Text = string.Empty;
            lbox_gr_user.DataSource = WrapNative.GetLocalGroupMembers(null, gname);
            lbox_user.DataSource = WrapNative.GetUserNames();

        }

2.4 그룹 내 멤버 목록(lbox_gr_user)의 항목 변경 이벤트 핸들러

그룹 내 멤버 목록(lbox_gr_user)의 항목 변경 이벤트 핸들러를 추가합니다.

선택 항목을 얻어옵니다.

선택 항목은 계정 경로로 “XXX\\계정이름”입니다.

이 때 \\뒤쪽 내용만 추출하여 텍스트 박스(tbox_sel_uname)의 Text 속성을 설정합니다.

        private void lbox_gr_user_SelectedIndexChanged(object sender, EventArgs e)
        {
            if(lbox_gr_user.SelectedIndex ==-1)
            {
                tbox_sel_uname.Text = string.Empty;
                btn_remove_user.Enabled = false;
                return;
            }
            btn_remove_user.Enabled = true;
            string user_name = lbox_gr_user.SelectedItem.ToString();
            int index = user_name.LastIndexOf("\\");
            if(index !=-1)
            {
                user_name = user_name.Substring(index + 1);
            }
            tbox_sel_uname.Text = user_name;
        }

2.5 계정 삭제 버튼(btn_remove_user)의 클릭 이벤트 핸들러

계정 삭제 버튼(btn_remove_user)의 클릭 이벤트 핸들러를 추가합니다.

계정을 삭제할 때도 DirectoryEntry 개체를 이용합니다.

“WinNT://[머신 이름], computer” 경로가 계정 Active Directory입니다.

DirectoryEntry 개체의 자식에서 선택한 계정 이름을 찾습니다.

찾은 개체가 존재하면 삭제합니다.

            string uname = tbox_sel_uname.Text;
            DirectoryEntry AD = new DirectoryEntry("WinNT://" +
                Environment.MachineName + ",computer");
            DirectoryEntry de = AD.Children.Find(uname);
            if(de != null)
            {
                AD.Children.Remove(de);                
            }

그룹 내 멤버 목록(lbox_gr_user)와 계정 목록(lbox_ser)을 갱신합니다.

            string gname = lb_gname.Text;
            lbox_gr_user.DataSource = WrapNative.GetLocalGroupMembers(null, gname);
            lbox_user.DataSource = WrapNative.GetUserNames();

다음은 계정 삭제 버튼(btn_remove_user)의 클릭 이벤트 핸들러 전체 코드입니다.

        private void btn_remove_user_Click(object sender, EventArgs e)
        {
            string uname = tbox_sel_uname.Text;
            DirectoryEntry AD = new DirectoryEntry("WinNT://" +
                Environment.MachineName + ",computer");
            DirectoryEntry de = AD.Children.Find(uname);
            if(de != null)
            {
                AD.Children.Remove(de);                
            }
            string gname = lb_gname.Text;
            lbox_gr_user.DataSource = WrapNative.GetLocalGroupMembers(null, gname);
            lbox_user.DataSource = WrapNative.GetUserNames();
        }

3. MainForm.cs 코드

다음은 MainForm.cs 코드입니다.

using System;
using System.DirectoryServices;
using System.Windows.Forms;
using WrapNativeLib;

namespace 계정_추가_삭제
{
    public partial class MainForm : Form
    {
        public MainForm()
        {
            InitializeComponent();
        }

        private void MainForm_Load(object sender, EventArgs e)
        {
            lbox_user.DataSource = WrapNative.GetUserNames();
            lbox_group.DataSource = WrapNative.GetGroupNames();

        }

        private void lbox_group_SelectedIndexChanged(object sender, EventArgs e)
        {
            string gname = string.Empty;
            if(lbox_group.SelectedIndex == -1)
            {
                return;
            }
            gname = lbox_group.SelectedItem.ToString();
            lb_gname.Text = gname;
            lbox_gr_user.DataSource = WrapNative.GetLocalGroupMembers(null, gname);

        }

        private void btn_add_user_Click(object sender, EventArgs e)
        {
            string uname = tbox_username.Text;
            DirectoryEntry AD = new DirectoryEntry("WinNT://" +
                Environment.MachineName + ",computer");
            DirectoryEntry new_user = AD.Children.Add(uname, "user");
            new_user.Invoke("Put", new object[] {"Description","WRU"});
            new_user.CommitChanges();
            string gname = "Guests";
            if (lbox_group.SelectedIndex != -1)
            {
                gname = lbox_group.SelectedItem.ToString();
            }

            DirectoryEntry grp = AD.Children.Find(gname, "group");
            if (grp != null)
            {
                grp.Invoke("Add", new object[] { new_user.Path.ToString() });
            }
            tbox_username.Text = string.Empty;
            lbox_gr_user.DataSource = WrapNative.GetLocalGroupMembers(null, gname);
            lbox_user.DataSource = WrapNative.GetUserNames();

        }

        private void lbox_gr_user_SelectedIndexChanged(object sender, EventArgs e)
        {
            if(lbox_gr_user.SelectedIndex ==-1)
            {
                tbox_sel_uname.Text = string.Empty;
                btn_remove_user.Enabled = false;
                return;
            }
            btn_remove_user.Enabled = true;
            string user_name = lbox_gr_user.SelectedItem.ToString();
            int index = user_name.LastIndexOf("\\");
            if(index !=-1)
            {
                user_name = user_name.Substring(index + 1);
            }
            tbox_sel_uname.Text = user_name;
        }

        private void btn_remove_user_Click(object sender, EventArgs e)
        {
            string uname = tbox_sel_uname.Text;
            DirectoryEntry AD = new DirectoryEntry("WinNT://" +
                Environment.MachineName + ",computer");
            DirectoryEntry de = AD.Children.Find(uname);
            if(de != null)
            {
                AD.Children.Remove(de);                
            }
            string gname = lb_gname.Text;
            lbox_gr_user.DataSource = WrapNative.GetLocalGroupMembers(null, gname);
            lbox_user.DataSource = WrapNative.GetUserNames();
        }

    }
}