2016-02-14 55 views
3

我正在学习C#并且是一名新手。请耐心等待我。PowerShell AD查询与C#AD查询 - 速度

我已经在C#中开发了一个应用程序,用于搜索AD中的用户,组和组成员,并通过Piping PowerShell命令进行搜索。

现在我试图在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"; 
} 

回答

5

在C#示例做了你由DirectorySearcher通过调用GetDirectoryEntry()隐含地执行两个额外查找每个对象

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()甚至提醒你一下:

注意
调用GetDirectoryEntry每个SearchResult中通过的DirectorySearcher返回可能会很慢。


你想要做的是添加你需要搜索(这是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 
} 
+0

嗨Mathias,谢谢你,但将代码更改为上面(没有GetDirectoryEntry())给了我一个错误“ResultPropertyValueCollection”不包含“价值”的定义.... 我错过了什么码? – Bhups