简体   繁体   English

尝试从 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#

This method is trying to get all OU's directory below the Center ou, one at a time, that match the names in my list of Center objects.此方法试图获取 Center ou 下的所有 OU 目录,一次一个,与我的 Center 对象列表中的名称匹配。

Next for each one it tries to set a couple properties (that have not been created before)接下来,它尝试为每个属性设置几个属性(之前尚未创建)

It gets the OU, goes to the .Add branch and crashes.它获取 OU,转到 .Add 分支并崩溃。 What am I misunderstanding.我有什么误解。

I get exception with "Unspecified error\\n\\n", with the following call stack我收到“未指定错误\\n\\n”的异常,具有以下调用堆栈

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

I've done this before but it was like 8 years ago.我以前这样做过,但就像 8 年前一样。 Thanks.谢谢。

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() );
                }
            }
        }

The only possible cause I can guess at is that ctr.ctrid is null or some weird type it can't handle.我能猜到的唯一可能的原因是ctr.ctridnull或者它无法处理的一些奇怪的类型。 But the error message of the exception will confirm that, if you can share that.但是异常的错误消息将确认这一点,如果您可以分享的话。

But some other comments:但其他一些评论:

Mysearcher.SearchScope = SearchScope.Subtree;

Subtree is the default, so you don't need to set it if that's what you want. Subtree是默认设置,因此如果您需要,则无需设置它。

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

UserPropertyCache is not an AD attribute. UserPropertyCache不是 AD 属性。 I think you are trying to use the UsePropertyCache (notice, no "r") property of DirectoryEntry , in which case you would do this:我认为你正在尝试使用UsePropertyCache (注意,没有“R”)的财产DirectoryEntry ,在这种情况下,你可以这样做:

centerDe.UsePropertyCache = true;

But true is the default anyway, so you don't need to do that.但是true无论如何都是默认值,所以你不需要这样做。

Then this:然后这个:

centerDe.RefreshCache();

Calling RefreshCache() tells it to go out to AD and retrieve every attribute for the object.调用RefreshCache()告诉它去 AD 并检索对象的每个属性。 The same thing happens when you read an attribute using Properties for the first time and the attribute is not in the cache yet.当您第一次使用Properties读取属性并且该属性尚未在缓存中时,也会发生同样的事情。 You could tell it to only retrieve the attributes you actually want to look at by doing this:您可以通过执行以下操作告诉它仅检索您实际想要查看的属性:

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

That will tell it to only retrieve those two attributes.这将告诉它只检索这两个属性。

However, you don't even need to do that.但是,您甚至不需要这样做。 All you're doing is adding a new value, so you don't really care what is already there.您所做的只是添加一个新值,因此您并不真正关心已经存在的值。

I see that you're switching between .Value = and .Add() depending on if there's a value already there, but you don't need to.我看到您在.Value =.Add()之间切换,具体取决于是否已经存在值,但您不需要。 You can just use .Add() and it will add a value whether there is something already there or not.您可以只使用.Add()并且它会添加一个值,无论是否已经存在某些东西。

And then there is this:然后是这个:

catch ( Exception ex )
{
    throw;
}

Is there a reason for this?是否有一个原因? As it is, there is no point to having the try/catch block at all if you are only going to rethrow it.事实上,如果您只想重新抛出它,那么使用 try/catch 块根本没有意义。

You can also simplify your code a little by using the continue statement.您还可以使用continue语句稍微简化您的代码。

Here is your code with all my recommendations included:这是您的代码,其中包含我的所有建议:

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() );
        }
    }
}

This will probably still throw an exception at .Add( ctr.ctrid ) , but you will have to share what the error message is before I can help with that.这可能仍会在.Add( ctr.ctrid )处引发异常,但在我提供帮助之前,您必须先分享错误消息的内容。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM