尝试从 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.ctrid
是 null
或它无法处理的某种奇怪类型。但是异常的错误信息会确认,如果你能分享的话。
但其他一些评论:
Mysearcher.SearchScope = SearchScope.Subtree;
Subtree
是默认设置,因此如果您需要,则无需设置它。
centerDe.Properties[ "UserPropertyCache" ].Value = true;
UserPropertyCache
不是 AD 属性。我认为您正在尝试使用 DirectoryEntry
的 UsePropertyCache
(注意,没有 "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 )
处抛出异常,但在我提供帮助之前,您必须先分享错误消息的内容。
此方法试图获取 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.ctrid
是 null
或它无法处理的某种奇怪类型。但是异常的错误信息会确认,如果你能分享的话。
但其他一些评论:
Mysearcher.SearchScope = SearchScope.Subtree;
Subtree
是默认设置,因此如果您需要,则无需设置它。
centerDe.Properties[ "UserPropertyCache" ].Value = true;
UserPropertyCache
不是 AD 属性。我认为您正在尝试使用 DirectoryEntry
的 UsePropertyCache
(注意,没有 "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 )
处抛出异常,但在我提供帮助之前,您必须先分享错误消息的内容。