尝试从 Active Directory 中检索 OU,然后使用 C# 中的目录条目在 OU 上设置新属性

Trying to Retrieve and OU from Active Directory, then set new properties on an OU using a Directory Entry in C#

此方法试图获取 Center ou 下的所有 OU 目录,一次一个,与我的 Center 对象列表中的名称相匹配。

接下来,它会尝试为每个属性设置几个属性(之前未创建)

它获取 OU,转到 .Add 分支并崩溃。我误会了什么。

我在 "Unspecified error\n\n" 中遇到异常,调用堆栈如下

at System.DirectoryServices.Interop.UnsafeNativeMethods.IAds.PutEx(Int32 lnControlCode, String bstrName, Object vProp) 在 System.DirectoryServices.PropertyValueCollection.OnInsertComplete(Int32 索引,对象值) 在 System.Collections.CollectionBase.System.Collections.IList.Add(对象值) 在 System.DirectoryServices.PropertyValueCollection.Add(对象值) 在 StudentPortalDevFixTool.Form1.buttonfixCenters_Click(Object sender, EventArgs e) 在 D:\TFS\StudentPortalDevFixTool\StudentPortalDevFixTool\Form1.cs:line 599

我以前做过,但好像是 8 年前的事了。谢谢

private void buttonfixCenters_Click( object sender, EventArgs e )
        {
            string adConnStr = ConfigurationSettings.AppSettings["DeUrl"];
            string adServerUser = ConfigurationSettings.AppSettings["DeAcct"];
            string adServerPassword = ConfigurationSettings.AppSettings["DePwd"];
            string adServerContainer = ConfigurationSettings.AppSettings["AD_DomainOu"];
            // looks like this: "DC=AD,DC=MyDomain,DC=org"

            if( !string.IsNullOrEmpty( adConnStr ) && !string.IsNullOrEmpty(adServerUser) && !string.IsNullOrEmpty(adServerPassword) && !string.IsNullOrEmpty(adServerContainer) )
            {
                string adName = textBox_adname_unlock.Text;

                try
                {
                    DirectoryEntry startSearch = new DirectoryEntry( adConnStr, adServerUser, adServerPassword );
                    foreach ( Center ctr in CenterListFromCdss )
                    {
                        try
                        {
                            DirectorySearcher Mysearcher;

                            if ( startSearch == null )
                            {
                                throw new Exception( "No root in BuildDirectoryEntry(...)" );
                            }

                            Mysearcher = new DirectorySearcher( startSearch );

                            Mysearcher.SearchScope = SearchScope.Subtree;
                            Mysearcher.Filter = "(&(objectCategory=organizationalUnit)(ou=" + ctr.shname + "))";

                            SearchResult result = Mysearcher.FindOne();

                            DirectoryEntry centerDe;

                            if ( result == null)
                            {
                                centerDe = null;
                            }
                            else
                            {
                                centerDe  = result.GetDirectoryEntry();
                            }


                            if ( centerDe != null )
                            {
                                centerDe.Properties[ "UserPropertyCache" ].Value = true; 
                                centerDe.RefreshCache();

                                if ( result.Properties.Contains( "telexNumber" ) )
                                {
                                    centerDe.Properties[ "telexNumber" ].Value = ctr.ctrid;
                                }
                                else
                                {
                                    centerDe.Properties[ "telexNumber" ].Add( ctr.ctrid );// GOES BOOM HERE!
                                }

                                if ( result.Properties.Contains( "centerCode" ) )
                                {
                                    centerDe.Properties[ "centerCode" ].Value = ctr.ctrCode;
                                }
                                else
                                {
                                    centerDe.Properties[ "centerCode" ].Add( ctr.ctrCode );
                                }

                                //centerDe.Properties[ "telexNumber" ].Value = ctr.ctrid;
                                //centerDe.Properties[ "centerCode" ].Value = ctr.ctrCode;

                                centerDe.CommitChanges();
                                centerDe.Close();
                            }
                        }
                        catch ( Exception ex )
                        {
                            throw;
                        }
                    }

                }
                catch (Exception ex)
                {
                    MessageBox.Show( "Exception: " + ex.ToString() );
                }
            }
        }

我能猜到的唯一可能原因是 ctr.ctridnull 或它无法处理的某种奇怪类型。但是异常的错误信息会确认,如果你能分享的话。

但其他一些评论:

Mysearcher.SearchScope = SearchScope.Subtree;

Subtree 是默认设置,因此如果您需要,则无需设置它。

centerDe.Properties[ "UserPropertyCache" ].Value = true;

UserPropertyCache 不是 AD 属性。我认为您正在尝试使用 DirectoryEntryUsePropertyCache(注意,没有 "r")属性,在这种情况下您会这样做:

centerDe.UsePropertyCache = true;

但是 true 无论如何都是默认值,因此您不需要这样做。

然后这个:

centerDe.RefreshCache();

调用 RefreshCache() 告诉它去 AD 并检索对象的 每个 属性。当您第一次使用 Properties 读取属性并且该属性尚未在缓存中时,也会发生同样的事情。你可以通过这样做告诉它只检索你真正想要查看的属性:

centerDe.RefreshCache(new [] { "telexNumber", "centerCode" });

这将告诉它只检索这两个属性。

但是,您甚至不需要这样做。您所做的只是添加一个新值,所以您并不真正关心已经存在的内容。

我看到您在 .Value =.Add() 之间切换,具体取决于是否已有值,但您不需要这样做。您可以只使用 .Add(),它会添加一个值,无论是否已经存在。

然后是这个:

catch ( Exception ex )
{
    throw;
}

这有什么原因吗?实际上,如果您只是想重新抛出 try/catch 块,那么根本没有意义。

您还可以使用 continue 语句稍微简化您的代码。

这是你的代码,其中包含我的所有建议:

private void buttonfixCenters_Click( object sender, EventArgs e )
{
    string adConnStr = ConfigurationSettings.AppSettings["DeUrl"];
    string adServerUser = ConfigurationSettings.AppSettings["DeAcct"];
    string adServerPassword = ConfigurationSettings.AppSettings["DePwd"];
    string adServerContainer = ConfigurationSettings.AppSettings["AD_DomainOu"];
    // looks like this: "DC=AD,DC=MyDomain,DC=org"

    if( !string.IsNullOrEmpty( adConnStr ) && !string.IsNullOrEmpty(adServerUser) && !string.IsNullOrEmpty(adServerPassword) && !string.IsNullOrEmpty(adServerContainer) )
    {
        string adName = textBox_adname_unlock.Text;

        try
        {
            DirectoryEntry startSearch = new DirectoryEntry( adConnStr, adServerUser, adServerPassword );
            foreach ( Center ctr in CenterListFromCdss )
            {
                DirectorySearcher Mysearcher;

                if ( startSearch == null )
                {
                    throw new Exception( "No root in BuildDirectoryEntry(...)" );
                }

                Mysearcher = new DirectorySearcher( startSearch );

                Mysearcher.Filter = "(&(objectCategory=organizationalUnit)(ou=" + ctr.shname + "))";

                SearchResult result = Mysearcher.FindOne();

                if ( result == null) continue;

                DirectoryEntry centerDe  = result.GetDirectoryEntry();

                centerDe.Properties[ "telexNumber" ].Add( ctr.ctrid.ToString() );
                centerDe.Properties[ "centerCode" ].Add( ctr.ctrCode.ToString() );

                centerDe.CommitChanges();
                centerDe.Close();
            }

        }
        catch (Exception ex)
        {
            MessageBox.Show( "Exception: " + ex.ToString() );
        }
    }
}

这可能仍会在 .Add( ctr.ctrid ) 处抛出异常,但在我提供帮助之前,您必须先分享错误消息的内容。