Getting users from an Active Directory group - c#

I have been banging my head for hours trying to figure out why this wont' work. I found an example of getting a list of users from an AD group but I can't get it to work. Here is what I've been trying to do:
DirectoryEntry de = new DirectoryEntry("LDAP://DC=" + domain + ",DC=com");
DirectorySearcher ds = new DirectorySearcher(de);//, "(objectClass=person)");
ds.Filter = "(&(objectCategory=person)(objectclass=user)(memberOf=CN=!CityNameGroup))";
ds.PropertiesToLoad.Add("givenname");
ds.PropertiesToLoad.Add("samaccountname");
ds.PropertiesToLoad.Add("sn");
ds.PropertiesToLoad.Add("useraccountcontrol");
foreach (SearchResult sr in ds.FindAll())
{//stuff goes here}
but ds.FindAll always brings back 0 results with this filter. I can do simpler filters that bring back results, but I never get anything back from the above filter. I just want all my users that are in the !CityNameGroup. I appreciate the help!

If .NET 3.5 is an option, stop banging your head and look here:
Everything in Active Directory via C#.NET 3.5 (Using System.DirectoryServices.AccountManagement)
Seriously, AD handling in .NET 3.5 is another world. It will change everything. For the better, of course.
Update
Also, there's a ready answer here ( Active Directory User Group Memberships GroupPrincipal ). I will have the decency of not copying it. :)
It uses .NET 3.5, BTW.

Related

AD UserPrincipal ChangePassword method creates user profile folders in C:\Users

We have a .NET Framework application used for changing user passwords. It uses the System.DirectoryServices.AccountManagement assembly.
Process goes as follows:
A user fills out a simple form (username, old pw, new pw, new pw repeated).
UserPrincipal.FindByIdentity() gets called to find the user
UserPrincipal.ChangePassword() gets called to change the password
Note: Principal context type is set to DOMAIN
Note2: everything works, the issue is with the user folders.
So apparently ChangePassword() creates a user profile in C:\Users folder in the application's machine and I cannot find any information why that happens. I would understand in the context was set to Machine, but in this case it's not.
There are over 6k folders now, one for each user, it's taking up a lot of space and slowing the machine down.
I tried recreating the problem locally and apparently the ChangePassword() creates a TEMP user profile in C:\Users in my computer, but then it disappears.
Code
Configuration
container.RegisterType<PasswordChangeService>(new InjectionFactory(m => new PasswordChangeService(
new PrincipalContext(ContextType.Domain, ConfigurationManager.AppSettings["LdapDomain"], ConfigurationManager.AppSettings["LdapQuery"]),
new LogService(new Persistence.LogDbContext())
)));
Code for finding user, changing password
using (var user = UserPrincipal.FindByIdentity(_principalContext, IdentityType.SamAccountName, passwordChange.Username)) {
if (user == null) {
Fail(passwordChange, "User not found");
}
user.ChangePassword(passwordChange.CurrentPassword, passwordChange.NewPassword);
LogSuccess(passwordChange);
}
Can anyone tell me why the user profiles get created?
How to fix this issue? Is this a configuration or permission problem?
(optional) I've seen examples where UserPrincipal.Save() gets called after, say, ChangePassword(), but it has always worked without it, so in what situation can it be used?
Thank you.
Update
after some unsuccessful searching I found out a few things that might be worth mentioning:
1. Someone from 2009 had the same problem technet link
The last comment "Since all the code snippets utilize the ChangePasword implementation of ADSI (which causes the profile generation) the simplest way to accomplish this programmatically would be to not use ADSI but System.DirectoryServices.Protocols instead and perform an attribute modification against unicodePwd".
2. When calling ChangePassword(), user directory was sometimes not created and at at those times Event Viewer showed a couple of errors
"Windows has backed up this user profile. Windows will automatically try to use the backup profile the next time this user logs on."
"Windows cannot find the local profile and is logging you on with a temporary profile. Changes you make to this profile will be lost when you log off."
3. Every "fix" I've seen resulted in fixing the consequence, but not the cause. I still have no idea why the profiles get created, but if the technet comment is legit, I guess I need to use another implementation.
I ended up using an example from SO link and this is my result:
string ldapPath = ConfigurationManager.AppSettings["LdapPath"];
string domainWithUserName = string.Format(ConfigurationManager.AppSettings["LdapDomain"], "\\", passwordChange.Username);
DirectoryEntry directoryEntry = new DirectoryEntry(ldapPath, domainWithUserName, passwordChange.CurrentPassword);
if (directoryEntry != null) {
DirectorySearcher search = new DirectorySearcher(directoryEntry);
search.Filter = "(SAMAccountName=" + passwordChange.Username + ")";
SearchResult result = search.FindOne();
if (result != null) {
DirectoryEntry userEntry = result.GetDirectoryEntry();
if (userEntry == null) {
Fail(passwordChange, "User not found.");
}
userEntry.Invoke("ChangePassword", new object[] { passwordChange.CurrentPassword, passwordChange.NewPassword});
userEntry.CommitChanges();
LogSuccess(passwordChange);
}
}
I still need to narrow down the AD search to a specific OU, etc.
This implementation works, no user profile gets created, Event Viewer shows nothing. It's a shame, really, because I'd rather call a few methods instead of using 15 lines of code that do the same thing.

Get build and changeset number from Team Foundation Server

I have been given a task to use the TFS API in order to check which build has which changeset number, after deployment. I haven't worked with TFS before, so mainly I've been trying to Google things, to find the answer. I've been at it for 2 days now, so I'm hoping someone can nudge me in the right direction...
Here is what I have done so far:
Uri collectionUri = new Uri("mytfs/tfs/");
var server = TfsConfigurationServerFactory.GetConfigurationServer(collectionUri);
server.Authenticate();
server.EnsureAuthenticated();
var service = server.GetService<TswaClientHyperlinkService>();
var projectCollection = TfsTeamProjectCollectionFactory.GetTeamProjectCollection(new Uri("mytfs/tfs/collection"));
var cssService = projectCollection.GetService<ICommonStructureService3>();
var project = cssService.GetProjectFromName("project");
WorkItemStore workItemStore = projectCollection.GetService<WorkItemStore>();
WorkItemCollection workItemCollection = workItemStore.Query("SELECT * FROM WorkItems");
So in the workItemCollection object, I tried a few queries, but it seems it doesn't allow me to change database, use joins etc. just a simple select/from statement.
Am I on the right track - is this how I should be getting build and changeset number?? If yes, where can I see what tables I need to query?
The problem here is that you're thinking of this as a database. It's not a database. It's an object model that allows you to programmatically access various aspects of TFS through a well-defined API.
Work item queries are not SQL, they are WIQL (work item query language). The work item object will definitely have a link to the associated changeset, but it won't have a link to a build. Some work item types have a field for "fixed in" that will be automatically updated with the build, but not all of them, so it's not necessarily reliable.
To find particular builds, you'll need to use the IBuildServer service and search for a build spec.

facebooktoolkit and C# photo upload problem

I need help with integrating facebook into my desktop application. It's developed with C# - target framework is .NET framework 4.0.
I'm using http://facebooktoolkit.codeplex.com/
The problem is that I can't get the users albums although my app has permission for it, and for all to be more confusing I can get statuses, comments, friends, etc.
I have this in designer:
this.fbMyApp = new Facebook.Winforms.Components.FacebookService(this.components);
this.fbMyApp.ApplicationKey = "myappkey_goes_here";
this.fbMyApp.SessionKey = null;
this.fbMyApp.uid = ((long)(0));
And I've used this code(I've set all permissions for testing purposes):
fbMyApp.ConnectToFacebook(new List<Facebook.Schema.Enums.ExtendedPermissions>() {
Facebook.Schema.Enums.ExtendedPermissions.create_event,
Facebook.Schema.Enums.ExtendedPermissions.create_note,
Facebook.Schema.Enums.ExtendedPermissions.email,
Facebook.Schema.Enums.ExtendedPermissions.offline_access,
Facebook.Schema.Enums.ExtendedPermissions.photo_upload,
Facebook.Schema.Enums.ExtendedPermissions.publish_stream,
Facebook.Schema.Enums.ExtendedPermissions.read_mailbox,
Facebook.Schema.Enums.ExtendedPermissions.read_stream,
Facebook.Schema.Enums.ExtendedPermissions.rsvp_event,
Facebook.Schema.Enums.ExtendedPermissions.share_item,
Facebook.Schema.Enums.ExtendedPermissions.sms,
Facebook.Schema.Enums.ExtendedPermissions.status_update,
Facebook.Schema.Enums.ExtendedPermissions.video_upload
});
Now if I do this(after user has logged in):
MessageBox.Show("TOTAL statuses: " + fbMyApp.Status.Get().Count.ToString());
I will get the number of user statuses, and could read them. However if I do this:
MessageBox.Show("TOTAL albums: " + fbMyApp.Photos.GetAlbums().Count.ToString());
I get zero, although user has about 10 albums. I need this, cause this way I can access the album IDs and could be able to upload a photo to specific album. Any idea why this isn't working or does anybody have any better suggestion for some facebook toolkit for C#?
You need to request "user_photos" permissions from Facebook. I haven't used this toolkit as I prefer to make simple graph rest calls dynamically instead of having a huge library. I imagine you could download the source and recompile it, adding the missing permission. You could also switch to this library which is alot more up to date with current Facebook functionality.

getting access to outlook exchange global address book

i am building a csharp application and i would like a dropdown list of all users in my outlook global address book (the same one when i click on To: from outlook gui. is this possible to get this progrmaticall? what are the security requirements here?
Security ramifications, in addition to the Outlook dependency left me unable to use this approach, in the past. As a result, I ended up building this in the form of an LDAP query. Another plus is that, (in response to your other question) you will be able to extract contact information because this information is stored in the Active Directory.
DISCLAIMER: It has been almost five years since I have looked at this code, so I'm afraid I no longer fully understand the query. Hopefully it's enough to get you started, however.
DirectoryEntry adFolderObject = new DirectoryEntry();
DirectorySearcher adSearcher = new DirectorySearcher(adFolderObject);
adSearcher.SearchScope = SearchScope.Subtree;
adSearcher.Filter = "(& (mailnickname=*) (| (&(objectCategory=person)(objectClass=user)(!(homeMDB=*))(!(msExchHomeServerName=*)))(&(objectCategory=person)(objectClass=user)(|(homeMDB=*)(msExchHomeServerName=*))) ))";
foreach (SearchResult adObject in adSearcher.FindAll())
{
Console.WriteLine("CN={0}, Path={1}", adObject.Properties["CN"][0], adObject.Path);
}

C# Active Directory Library

Has anyone seen any solid libraries for working with active directory (mainly user related stuff) in C# and asp.net. Am I better off intergrating with asp membership or building something customised.
I took a look at LINQtoAD but it doesnt seem to be active anymore.
Is the System.DirectoryServices assembly and namespace insufficient?
If you're on .NET 3.5, also check out System.DirectoryServices.AccountManagement for much simpler interface when it comes to handling principals - users, groups, computers etc.
Check out this MSDN article as a great intro into S.DS.AD:
Managing Directory Security Principals in the .NET Framework 3.5
Cheers!
You can refer my OSS project which base on ActiveRecord pattern as following(Because it is open source you can find out how to operate the AD with DirectoryEntry, DirectoryEntry is not only support the LDAP protocol but also IIS, WIN and so on, so I develop this lib):
Eg: Update a user AD object.
using (var userObject = UserObject.FindOneByCN(this.ADOperator, “pangxiaoliang”))
{
if(userObject.Email == "example#landpy.com")
{
userObject.Email = "mv#live.cn";
userObject.Save();
}
}
Eg: Query user AD objects.
// 1. CN end with "liu", Mail conatains "live" (Eg: mv#live.cn), job title is "Dev" and AD object type is user.
// 2. CN start with "pang", Mail conatains "live" (Eg: mv#live.cn), job title is "Dev" and AD object type is user.
IFilter filter =
new And(
new IsUser(),
new Contains(PersonAttributeNames.Mail, "live"),
new Is(PersonAttributeNames.Title, "Dev"),
new Or(
new StartWith(AttributeNames.CN, "pang"),
new EndWith(AttributeNames.CN, "liu")
)
);
// Output the user object display name.
foreach (var userObject in UserObject.FindAll(this.ADOperator, filter))
{
using (userObject)
{
Console.WriteLine(userObject.DisplayName);
}
}
Eg: Custom query.
IFilter filter =
new And(
new IsUser(),
new Custom("(!userAccountControl:1.2.840.113556.1.4.803:=2)")
);
// Output the user object display name.
foreach (var userObject in UserObject.FindAll(this.ADOperator, filter))
{
using (userObject)
{
Console.WriteLine(userObject.DisplayName);
}
}
https://landpyactivedirectory.codeplex.com/documentation
And you will find it easy to operate the AD with it, if you have no interest with it please ignore my answer. Any question about AD please contact me :)

Categories

Resources