我正在学习C#并且是新手。请耐心等待。
我在C#中开发了一个应用程序,通过将PowerShell命令输入到AD中来搜索AD中的用户,组和组成员。
现在我正在尝试使用C#中的DirectoryServices来获得相同的结果,但是获取相同结果所需的时间比PowerShell中的时间长得多。
以下是我正在使用DirectoryServices进行快速测试的内容:
using System.DirectoryServices;
using System.DirectoryServices.ActiveDirectory;
private void button1_Click(object sender, EventArgs e)
{
string textbox = textBox1.Text.ToString();
listBox1.Items.Clear();
listView1.Items.Clear();
listView1.Columns.Clear();
try
{
// Bind to the object for which to retrieve property data.
DirectoryEntry de = new DirectoryEntry("");
DirectorySearcher ds = new DirectorySearcher(de);
ds.Filter = "(&(objectClass=Group)(cn="+ textbox + "))";
ds.SearchScope = SearchScope.Subtree;
SearchResultCollection rsAll = ds.FindAll();
listView1.Columns.Add("samsaccountname");
string samsaccountname = "";
foreach (SearchResult searchresult in rsAll)
{
if (searchresult.GetDirectoryEntry().Properties["samaccountname"].Value != null)
{ samsaccountname = searchresult.GetDirectoryEntry().Properties["samaccountname"].Value.ToString(); }
else { samsaccountname = ""; }
ListViewItem lvi = new ListViewItem(samsaccountname);
//lvi.SubItems.Add(givenName);
//lvi.SubItems.Add(sn);
//lvi.SubItems.Add(mail);
listView1.Items.Add(lvi);
}
listView1.AutoResizeColumns(ColumnHeaderAutoResizeStyle.ColumnContent);
}
catch
{
// Add error handling.
}
}
以下是我在PowerShell + C#中所做的事情
private string SearchDLScript(string searchDL)
{
listViewSearchDL.Items.Clear();
listViewSearchDL.Columns.Clear();
listViewSearchDL.Columns.Add("");
listViewSearchDL.Items.Add("Loading list, please wait.");
listViewSearchDL.AutoResizeColumns(ColumnHeaderAutoResizeStyle.HeaderSize);
if (textSearchDL.Text.Length < 8)
{
listViewSearchDL.Items.Add("Hint: The more you type, the quicker the seach.");
listViewSearchDL.AutoResizeColumns(ColumnHeaderAutoResizeStyle.HeaderSize);
}
string rbName = "";
if (radioButtonDisplayName.Checked == true)
{
rbName = "DisplayName";
} else if (radioButtonAlias.Checked == true)
{
rbName = "SamAccountName";
}
string searchDLScriptCommand = @"Import-Module ActiveDirectory
Get-ADGroup -Filter '"+rbName+ @" -Like """ + searchDL + @"*"" ' -Properties * | Select-Object DisplayName,SamAccountName | ConvertTo-Csv -NoTypeInformation | Select-Object -Skip 1";
string scriptOutput = RunPowerShellCommands.RunPowerShellCode(searchDLScriptCommand);
string[] strArr = scriptOutput.Split(new string[] { System.Environment.NewLine }, StringSplitOptions.None);
strArr = strArr.Where(x => !string.IsNullOrEmpty(x)).ToArray();
listViewSearchDL.Columns.Clear();
listViewSearchDL.Items.Clear();
listViewSearchDL.Columns.Add("Display Name");
listViewSearchDL.Columns.Add("Alias");
foreach (string user in strArr)
{
string userDetails = user.Replace("\"", "");
string[] columns = userDetails.Split(',');
ListViewItem lvi = new ListViewItem(columns[0]);
for (int i = 1; i < columns.Count(); i++)
{
lvi.SubItems.Add(columns[i]);
}
listViewSearchDL.Items.Add(lvi);
}
if (scriptOutput == "\r\n")
{
listViewSearchDL.Items.Clear();
listViewSearchDL.Columns.Clear();
listViewSearchDL.Columns.Add("");
listViewSearchDL.Items.Add("There are no records");
}
listViewSearchDL.AutoResizeColumns(ColumnHeaderAutoResizeStyle.ColumnContent);
listViewSearchDL.AutoResizeColumns(ColumnHeaderAutoResizeStyle.HeaderSize);
return "scriptOutput";
}
答案 0 :(得分:5)
在C#示例中,您通过调用GetDirectoryEntry()
隐式执行DirectorySearcher返回的两个额外查找每个对象:
foreach (SearchResult searchresult in rsAll)
{
if (searchresult.GetDirectoryEntry().Properties["samaccountname"].Value != null)
{ samsaccountname = searchresult.GetDirectoryEntry().Properties["samaccountname"].Value.ToString(); }
else { samsaccountname = ""; }
// and then updating the listview
}
The documentation for GetDirectoryEntry()
甚至警告过你:
注意强>
在通过DirectorySearcher返回的每个SearchResult上调用GetDirectoryEntry可能会很慢。
你想要做的是将你需要的属性名称列表添加到搜索器中(这是Get-AD* -Properties
参数在后台执行的操作),并在第一个之后返回它们搜索:
DirectorySearcher ds = new DirectorySearcher(de);
// do this before calling FindAll()
ds.PropertiesToLoad.Add("samaccountname")
然后在处理搜索结果时,直接从每个搜索结果中获取属性值,而不是再次调用GetDirectoryEntry()
:
foreach (SearchResult searchresult in rsAll)
{
if (searchresult.Properties["samaccountname"].Value != null)
{
samsaccountname = searchresult.Properties["samaccountname"].Value.ToString();
}
else
{
samsaccountname = "";
}
// and then updating the listview
}