C# 尝试从Active Directory检索和设置OU,然后使用C中的目录项在OU上设置新属性#
此方法尝试获取中心OU下的所有OU目录,一次一个,与我的中心对象列表中的名称匹配 接下来,它会尝试为每个属性设置一对属性(以前未创建过的属性) 它获取OU,转到.Add分支并崩溃。我误解了什么 我得到“未指定错误\n\n”异常,调用堆栈如下 位于System.DirectoryServices.Interop.UnsafentiveMethods.IAds.PutEx(Int32 lnControlCode、字符串bstrName、对象vProp) 位于System.DirectoryServices.PropertyValueCollection.OnInsertComplete(Int32索引,对象值) 位于System.Collections.CollectionBase.System.Collections.IList.Add(对象值) 位于System.DirectoryServices.PropertyValueCollection.Add(对象值) 在StudentPortalDevFixTool.Form1.button输入\单击D:\TFS\StudentPortalDevFixTool\StudentPortalDevFixTool\Form1.cs:第599行中的(对象发送者,事件参数e) 我以前做过,但那是8年前的事了。谢谢C# 尝试从Active Directory检索和设置OU,然后使用C中的目录项在OU上设置新属性#,c#,active-directory,directoryservices,C#,Active Directory,Directoryservices,此方法尝试获取中心OU下的所有OU目录,一次一个,与我的中心对象列表中的名称匹配 接下来,它会尝试为每个属性设置一对属性(以前未创建过的属性) 它获取OU,转到.Add分支并崩溃。我误解了什么 我得到“未指定错误\n\n”异常,调用堆栈如下 位于System.DirectoryServices.Interop.UnsafentiveMethods.IAds.PutEx(Int32 lnControlCode、字符串bstrName、对象vProp) 位于System.DirectoryServi
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
不是广告属性。我认为您正在尝试使用DirectoryEntry
的(注意,无“r”)属性,在这种情况下,您可以这样做:
centerDe.UsePropertyCache = true;
但是true
是默认值,所以您不需要这样做
那么这个,
centerDe.RefreshCache();
调用RefreshCache()
告诉它转到AD并检索对象的每个属性。当您第一次使用Properties
读取属性,而该属性尚未在缓存中时,也会发生同样的情况。通过执行以下操作,您可以告诉它仅检索实际要查看的属性:
centerDe.RefreshCache(new [] { "telexNumber", "centerCode" });
这将告诉它只检索这两个属性
然而,你甚至不需要这样做。你所做的只是增加一个新的价值,所以你并不真正关心已经存在的东西
我看到您正在.Value=
和.Add()
之间切换,这取决于是否已经存在值,但您不需要这样做。您只需使用.Add()
,无论是否已经存在某个内容,它都会添加一个值
还有这个:
catch ( Exception ex )
{
throw;
}
这有什么原因吗?事实上,如果您只想重新播放try/catch块,那么使用try/catch块是毫无意义的
您还可以使用该语句稍微简化代码
以下是您的代码以及我的所有建议:
private void按钮输入\u单击(对象发送者,事件参数e)
{
字符串adConnStr=ConfigurationSettings.AppSettings[“DeUrl”];
字符串adServerUser=ConfigurationSettings.AppSettings[“DeAcct”];
字符串adServerPassword=ConfigurationSettings.AppSettings[“DePwd”];
字符串adServerContainer=ConfigurationSettings.AppSettings[“AD_DomainOu”];
//看起来像这样:“DC=AD,DC=MyDomain,DC=org”
如果(!string.IsNullOrEmpty(adConnStr)和&!string.IsNullOrEmpty(adServerUser)和&!string.IsNullOrEmpty(adServerPassword)和&!string.IsNullOrEmpty(adServerContainer))
{
字符串adName=textBox\u adName\u unlock.Text;
尝试
{
DirectoryEntry startSearch=新的DirectoryEntry(adConnStr、adServerUser、adServerPassword);
foreach(中心列表中的中心中心中心来自CDSS)
{
我的搜索者;
if(startSearch==null)
{
抛出新异常(“BuildDirectoryEntry中没有根(…)”;
}
Mysearcher=新的目录搜索器(startSearch);
mysearch.Filter=“(&(objectCategory=organizationalUnit)(ou=“+ctr.shname+”)”;
SearchResult=Mysearcher.FindOne();
如果(结果==null)继续;
DirectoryEntry centerDe=result.GetDirectoryEntry();
centerDe.Properties[“电传号码”].Add(ctr.ctrid.ToString());
centerDe.Properties[“centerCode”].Add(ctr.ctrCode.ToString());
centerDe.CommitChanges();
centerDe.Close();
}
}
捕获(例外情况除外)
{
Show(“异常:+ex.ToString());
}
}
}
这可能仍然会在
.Add(ctr.ctrid)
上引发异常,但您必须先分享错误消息,然后我才能提供帮助。ctrid=2刷新缓存的内容,谢谢,我是从另一个线程上的评论中得到的,现在我明白发生了什么。捕获并重新抛出一个异常,这样我就可以在抛出异常的方法中放置一个断点。这纯粹是为了调试。在一个不那么普通的应用程序*(这是一个一次性工具)中,我也会把它记录在那里。我更新了它以显示异常消息,可能是在您键入此答案时。我收到“Unspecified error\n\n”异常,调用堆栈位于原始消息中,因为消息没有太大帮助。谢谢因此,该值为2
。在我做的小测试中,我猜它不是int
。因为如果我做了.Add(2)
,它工作得很好。但是如果我执行.Add(2d)
(强制它使用十进制
类型),那么它将失败,并出现相同的错误。只需对其调用.ToString()
。我更新了我的答案。我添加了.ToString()(因为它是Int64)并现在设置,但当我提交更改时,我得到“指定的目录服务属性或值不存在”。我如何添加新的不存在的设置,如CenterCode?这将需要修改您的AD计划