错误 adding/removing 通过 .NET 的 Outlook 通讯组列表用户
Error adding/removing Outlook Distribution List users through .NET
我是多个 Outlook 分发列表 (DL) 的共同所有者。我可以在 Outlook 中编辑它们,直接在其中添加和删除成员。但是,我无法通过简单的 .NET 程序编辑它们:
using System;
using System.DirectoryServices.AccountManagement;
namespace DL_Remove_User
{
class Program
{
static void Main(string[] args)
{
try
{
RemoveUser("My Distribution List", "jimtut");
}
catch (Exception ex)
{
Console.WriteLine("Error: " + ex.ToString());
}
}
private static void RemoveUser(string dl, string username)
{
using (PrincipalContext pc = new PrincipalContext(ContextType.Domain, "CORP"))
{
GroupPrincipal group = GroupPrincipal.FindByIdentity(pc, dl);
bool result = group.Members.Remove(pc, IdentityType.SamAccountName, username);
Console.WriteLine(result.ToString());
group.Save();
}
}
}
}
同样的代码适用于许多其他 DL,但对于一对夫妇,我收到消息 "Access is Denied"。完整堆栈跟踪:
at System.DirectoryServices.Interop.UnsafeNativeMethods.IAds.SetInfo()
at System.DirectoryServices.DirectoryEntry.CommitChanges()
at System.DirectoryServices.AccountManagement.ADStoreCtx.UpdateGroupMembership(Principal group, DirectoryEntry de, NetCred credentials, AuthenticationTypes authTypes)
at System.DirectoryServices.AccountManagement.SDSUtils.ApplyChangesToDirectory(Principal p, StoreCtx storeCtx, GroupMembershipUpdater updateGroupMembership, NetCred credentials, AuthenticationTypes authTypes)
at System.DirectoryServices.AccountManagement.ADStoreCtx.Update(Principal p)
at System.DirectoryServices.AccountManagement.Principal.Save()
at Department_Distribution_Lists.Program.RemoveUser(String dl, String username) in Program.cs:line 483
当然,"Access is denied"确实表示权限问题,但我可以直接在 Outlook 中编辑这些 DL。我什至可以在 AD/LDAP 中查询 DL "owners",并且我在集合 "msExchCoManagedByLink".
中
关于为什么我可以在 Outlook 中编辑但不能通过 .NET 编辑的任何想法?
我终于明白了。我对这个权限问题感到困惑,因为我可以在 Outlook 中编辑 DL,但不能通过 .NET。
我开始寻找我可以通过 .NET 编辑的 DL 和我不能编辑的 DL 之间的差异,发现差异在 AD 属性 中表示,在此 GUI 中显示为 "Manager can update membership list":
即使我是 "manager"(列表所有者),如果 DL 没有 属性 设置,我只能在 Outlook 中编辑。
我不想目视检查所有 DL,所以我编写了以下代码来检测 DL 的 "real" owners/editors:
static List<string> GetGroupOwners(GroupPrincipal group)
{
List<string> owners = new List<string>();
DirectoryEntry deGroup = group.GetUnderlyingObject() as DirectoryEntry;
ActiveDirectorySecurity ads = deGroup.ObjectSecurity;
AuthorizationRuleCollection rules = ads.GetAccessRules(true, true, typeof(SecurityIdentifier));
Guid exRight_Member = new Guid("{bf9679c0-0de6-11d0-a285-00aa003049e2}");
foreach (ActiveDirectoryAccessRule ar in rules)
{
if (ar.ActiveDirectoryRights.HasFlag(ActiveDirectoryRights.GenericWrite) || (ar.ObjectType.Equals(exRight_Member) && ar.ActiveDirectoryRights.HasFlag(ActiveDirectoryRights.WriteProperty)))
{
string friendlyName = "";
try
{
friendlyName = ar.IdentityReference.Translate(typeof(NTAccount)).Value;
}
catch
{
}
owners.Add(friendlyName);
}
}
return owners;
}
如果您想知道谁拥有基于 Outlook 的编辑权限,那就不同了:
static List<string> GetGroupOwnersOutlook(GroupPrincipal group)
{
List<string> owners = new List<string>();
DirectoryEntry deGroup = group.GetUnderlyingObject() as DirectoryEntry;
System.DirectoryServices.PropertyCollection r = deGroup.Properties;
foreach (string a in r["managedBy"])
{
owners.Add(a);
}
foreach (string a in r["msExchCoManagedByLink"])
{
owners.Add(a);
}
return owners;
}
我是多个 Outlook 分发列表 (DL) 的共同所有者。我可以在 Outlook 中编辑它们,直接在其中添加和删除成员。但是,我无法通过简单的 .NET 程序编辑它们:
using System;
using System.DirectoryServices.AccountManagement;
namespace DL_Remove_User
{
class Program
{
static void Main(string[] args)
{
try
{
RemoveUser("My Distribution List", "jimtut");
}
catch (Exception ex)
{
Console.WriteLine("Error: " + ex.ToString());
}
}
private static void RemoveUser(string dl, string username)
{
using (PrincipalContext pc = new PrincipalContext(ContextType.Domain, "CORP"))
{
GroupPrincipal group = GroupPrincipal.FindByIdentity(pc, dl);
bool result = group.Members.Remove(pc, IdentityType.SamAccountName, username);
Console.WriteLine(result.ToString());
group.Save();
}
}
}
}
同样的代码适用于许多其他 DL,但对于一对夫妇,我收到消息 "Access is Denied"。完整堆栈跟踪:
at System.DirectoryServices.Interop.UnsafeNativeMethods.IAds.SetInfo()
at System.DirectoryServices.DirectoryEntry.CommitChanges()
at System.DirectoryServices.AccountManagement.ADStoreCtx.UpdateGroupMembership(Principal group, DirectoryEntry de, NetCred credentials, AuthenticationTypes authTypes)
at System.DirectoryServices.AccountManagement.SDSUtils.ApplyChangesToDirectory(Principal p, StoreCtx storeCtx, GroupMembershipUpdater updateGroupMembership, NetCred credentials, AuthenticationTypes authTypes)
at System.DirectoryServices.AccountManagement.ADStoreCtx.Update(Principal p)
at System.DirectoryServices.AccountManagement.Principal.Save()
at Department_Distribution_Lists.Program.RemoveUser(String dl, String username) in Program.cs:line 483
当然,"Access is denied"确实表示权限问题,但我可以直接在 Outlook 中编辑这些 DL。我什至可以在 AD/LDAP 中查询 DL "owners",并且我在集合 "msExchCoManagedByLink".
中关于为什么我可以在 Outlook 中编辑但不能通过 .NET 编辑的任何想法?
我终于明白了。我对这个权限问题感到困惑,因为我可以在 Outlook 中编辑 DL,但不能通过 .NET。
我开始寻找我可以通过 .NET 编辑的 DL 和我不能编辑的 DL 之间的差异,发现差异在 AD 属性 中表示,在此 GUI 中显示为 "Manager can update membership list":
即使我是 "manager"(列表所有者),如果 DL 没有 属性 设置,我只能在 Outlook 中编辑。
我不想目视检查所有 DL,所以我编写了以下代码来检测 DL 的 "real" owners/editors:
static List<string> GetGroupOwners(GroupPrincipal group)
{
List<string> owners = new List<string>();
DirectoryEntry deGroup = group.GetUnderlyingObject() as DirectoryEntry;
ActiveDirectorySecurity ads = deGroup.ObjectSecurity;
AuthorizationRuleCollection rules = ads.GetAccessRules(true, true, typeof(SecurityIdentifier));
Guid exRight_Member = new Guid("{bf9679c0-0de6-11d0-a285-00aa003049e2}");
foreach (ActiveDirectoryAccessRule ar in rules)
{
if (ar.ActiveDirectoryRights.HasFlag(ActiveDirectoryRights.GenericWrite) || (ar.ObjectType.Equals(exRight_Member) && ar.ActiveDirectoryRights.HasFlag(ActiveDirectoryRights.WriteProperty)))
{
string friendlyName = "";
try
{
friendlyName = ar.IdentityReference.Translate(typeof(NTAccount)).Value;
}
catch
{
}
owners.Add(friendlyName);
}
}
return owners;
}
如果您想知道谁拥有基于 Outlook 的编辑权限,那就不同了:
static List<string> GetGroupOwnersOutlook(GroupPrincipal group)
{
List<string> owners = new List<string>();
DirectoryEntry deGroup = group.GetUnderlyingObject() as DirectoryEntry;
System.DirectoryServices.PropertyCollection r = deGroup.Properties;
foreach (string a in r["managedBy"])
{
owners.Add(a);
}
foreach (string a in r["msExchCoManagedByLink"])
{
owners.Add(a);
}
return owners;
}