Hi all,
There are a couple of dozen posts here on MIBUSO that ask the same question in a variety of ways: "How can I see/list/determine which Windows (Active Directory) groups a user belongs to from inside NAV via C/AL code?
The method that works successfully in 2009 is to use the "User SID" virtual table - this works great as long as you are looking at the current user. It doesn't work if you are trying to determine if a different user's groups. However, the "User SID" virtual table does not exist in NAV2016
Other suggestions say to use DotNet functions - but I haven't seen any C/AL code that actually does this except for one example - and that example parses the entire Active Directory, so if you have lots of users and lots of groups, this takes a very long time to process.
Another suggestion is to create a linked SQL server and ADO to query active directory.
So, has anyone seen or created an efficient way to return a list of Windows Groups for a User from within C/AL code?
Thanks
Ron
Ron
0
Answers
Archerpoint India Pvt. Ltd,Chennai.
But thank you for taking the time to reply.
Ron
The simplified code here calls a .NET dll I wrote in VS. This is the best way for me to get access to the full LDAP object of the security group or user, their details and groups. You could also e.g. use it to get the manager and add it to the approval setup automatically also.
I used this to assess what to do with the user. The user is already in place after getting the users from the security group first.
SecurityGroups := SecurityGroups.SecurityGroups(); // instantiate .NET
MyText := SecurityGroups.GetADUsersGroups(FORMAT(UserName)); // Send the user as a parameter
Separator := '|'; // agreed separator with dll code.
ValueArray := MyText.Split(Separator.ToCharArray()); // return the list
IF ValueArray.ToString <> '' THEN BEGIN
FOREACH Value IN ValueArray DO BEGIN
//DoSomething like compare NAV groups to Windows groups of the user
END;
END;
in the dll I would search the LDAP e.g:
public string GetADUsersGroups(string loginName)
{
returnstring = SearchUserbyLDAPDomain(loginName, "LDAP://region.companynet.org:123");
if (returnstring != "")
{
return returnstring;
}
}
private string SearchUserbyLDAPDomain(string loginName, string domain)
{
DirectoryEntry entry = new DirectoryEntry(domain);
DirectorySearcher search = new DirectorySearcher(entry);
SearchResult result;
string cnname = "";
string returnstring = "";
string userName = ExtractUserName(loginName);
search.Filter = String.Format("(SAMAccountName={0})", userName);
search.PropertiesToLoad.Add("cn");
try
{
result = search.FindOne();
cnname = (string)result.Properties["cn"][0];
search.Filter = String.Format("(cn={0})", cnname);
search.PropertiesToLoad.Add("memberOf");
StringBuilder groupsList = new StringBuilder();
result = search.FindOne();
if (result != null)
{
int groupCount = result.Properties["memberOf"].Count;
for (int counter = 0; counter < groupCount; counter++)
{
string group = (string)result.Properties["memberOf"][counter];
group = group.Substring(group.IndexOf("CN=") + 3);
int index = group.IndexOf(",");
if (index > 0)
group = group.Substring(0, index);
groupsList.Append((string)group);
groupsList.Append("|");
}
}
if (groupsList.Length > 1)
{
groupsList.Length -= 1;
returnstring = groupsList.ToString();
}
return returnstring.ToString();
}
catch
{
return returnstring.ToString();
}
}
private string ExtractUserName(string path)
{
string[] userPath = path.Split(new char[] { '\\' });
return userPath[userPath.Length - 1];
}
I hope this helps
Ron