C# get obscure Active Directory Attributes - c#

I'm trying to retrieve some obsure Active Directory Attributes:
msexchmailboxsecuritydescriptor, and
terminalservicesprofilepath (in userparameters)
I am having trouble getting to both of them.
For example, for msexchmailboxsecuritydescriptor, if I have code similar to the following:
DirectoryEntry deresult = result.GetDirectoryEntry();
byte[] bteMailACL =(byte[])deresult.Properties["msexchmailboxsecuritydescriptor"].Value;
It complains that I cannot cast System.__ComObject to System.Byte[], but I have seen several example that use code similar to the above.
How do I understand these blobs of information?

I think your problem is in .Value part of the statement. Not sure how the examples have been doing it but I've noticed that whenever I call an AD Property like that, I always get an array back of which I get index 0 in case of single result items.
just changing the last statment to:
byte[] btwMailACL = (byte[])deresult.Properties["msexchmailboxsecuritydescriptor"][0];
solves your problem.
Edit: for production code, please do remember that this can throw a NullReferenceException so do check if the property actually returned a value before calling on the index.
(Tested on my machine and working as above)

Related

LDAP property contains to many values

I have a function witch tries to remove a member from a group
The problem is if you try to remove a member, without knowing the existence in the group, you could cause an exception.
So I try to enumerate its membership beforehand.
The problem now is that the member property stops after 3000 Entries, and I don't know a way to get more, or the next 3000 members of that group.
Here is my code
DirectoryEntry target_group = new DirectoryEntry(LDAP_group_DN);
if (target_group.Properties["member"].Contains(LDAP_member_to_remove_DN)) {
target_group.Properties["member"].Remove(LDAP_member_to_remove_DN);
}
target_group.CommitChanges();
target_group.Properties["member"] contains exactly 3000 entries, but in reality it is around 7500.
As a shorthand fix I am using the remove statement in a try/catch block without the .Contains() check, but that doesn't seem correct/beautiful/right.
Can anyone lead me to the correct way?
PS: I can not change the structure of our Directory.
This is a Group of RADIUS users, with should not be split up in more groups!
Instead of getting all the group members to determine if the user is part of that list I would use the memberOf/isMemberOf attribute (assuming that your directory supports this feature). This attribute will tell you if a user belongs to a group without having to retrieve all group members.
This other answer might help.
You need to look at into MaxValRange and learn how to retrieve more values using C#.
We have a very simple sample, but, alas, it is in Java

Rethinkdb .net update value

I'm looking at updating stored values in a RethinkDB using the C# RethinkDB.Driver library and I'm just not getting it right.
I can achieve an update by getting the result, altering that object then making a separate call to update with that object. When there are many calls to a record to update like this, the value being updated elsewhere whilst the application is working with the record.
TestingObject record = r.Db("test").Table("learning").Get("c8c54346-e35f-4025-8641-7117f12ebc5b").Run(_conn);
record.fieldNameIntValue = record.fieldNameIntValue + 1;
var result = r.Db("test").Table("learning").Get("c8c54346-e35f-4025-8641-7117f12ebc5b").Update(record).Run(_conn);
I've been trying something along these lines :
var result = r.Db("test").Table("learning").Get("c8c54346-e35f-4025-8641-7117f12ebc5b").Update(row => row["fieldNameIntValue"].Add(1)).Run(_conn);
but the result errors with Inserted value must be an OBJECT (got NUMBER):101 which suggests this is only passing the field value back instead of updating the object.
Ideally I'd like to update multiple columns at once, any advice is appreciated :)
This is an example that works in the ReQL data explorer. You can chain as may filters before the update as you want. I assume this will translate to the C# Driver, but I dont have any experience with that.
r.db('database').table('tablename').update({clicks: r.row("clicks").add(1)}).run().then(function(result){ ...
Thanks T Resudek your answer and a clearer head helped emphasised the need to map the calculation to the property.
Looking at the javadocs for update it has HashMap method which I followed with the c# library and it works.
var result = r.Db("test").Table("learning").Get("c8c54346-e35f-4025-8641-7117f12ebc5b").Update(row => r.HashMap("fieldNameIntValue",row["fieldNameIntValue"].Add(1))).Run(_conn);
I'd be interested to know if this is the right way or was a better way.

Unable to retrieve information from some of the WorkItem Fields in TFS

So these days I am trying to work with the TFS API. So far it was good, but all of a sudden.. I want to retrieve specific story's work items and their respective information using a search by ID method to pick the correct story. In order not to miss some important information I am doing SELECT * in my queries. I get the story, I get the Tasks.. But there seems to be problem with few of the fields - namely AreaPath, IterationPath and Type. As a primitive check I've written down some Console prints to check what's good and what's not - so if I uncomment any of the three previously named on execution this exception is thrown: A first chance exception of type 'Microsoft.TeamFoundation.WorkItemTracking.Client.FieldDefinitionNotExistException' occurred in Microsoft.TeamFoundation.WorkItemTracking.Client.dll.
Here is what I am trying to print out:
Console.WriteLine(target.Fields["Title"].Value);
Console.WriteLine(target.Fields["Description"].Value);
Console.WriteLine(int.Parse(target.Fields["Id"].Value.ToString()));
Console.WriteLine(target.Fields["AreaPath"].Value); //Problem 1
Console.WriteLine(target.Fields["IterationPath"].Value); //Problem 2
Console.WriteLine(int.Parse(target.Fields["AreaId"].Value.ToString()));
Console.WriteLine(int.Parse(target.Fields["IterationId"].Value.ToString()));
Console.WriteLine(target.Fields["State"].Value);
Console.WriteLine(target.Fields["Type"].Value.ToString()); //Problem 3
With or without ToString() nothing really changes.
Any suggestions ?
EDIT: They are not null, I've checked while in Debug mode, they all have assigned values.
Use CoreField or builtin getters:
Console.WriteLine(target.Fields[CoreField.Title].Value);
Console.WriteLine(target.Fields[CoreField.AreaPath].Value);
Console.WriteLine(target.State);
Console.WriteLine(target.Type.Name);

Trying to get name of data stored in reader

I have datareader which reads through 5 names with different values attached to each name.
While debugging i can get to each name using this expression computed by VS:
(new System.Collections.Generic<System.IO.FileInfo>(((School.PackageReader)(reader))._incomingStudents)).Items[0].Name
This above code while debugging gives me values i need like 5 different names when i change Items from 0 to 1 or 2... But when i try to use above code in my .cs file i get errors. Is there anyway to use this in code and get the values?
The error you are receiving is because you did not define the type of Collection you wanted to use.
I assume you are looking for a List, in which case you need to instantiate it this way:
(new System.Collections.Generic.List<System.IO.FileInfo>(((School.PackageReader)(reader))._incomingStudents)).Items[0].Name
Though it doesn't seem like this would be a good case for a List as you are calling a single value in Items[0].Name. BUT that's where your error is coming from.

Retrieving friendly name as claims user in SharePoint

I'll explain what I'm trying to do first. I have a claims identifier being passed in, for example, 0e.t|saml provider|first.last#domain.local. I want to trim that to first.last#domain.local.
I am well aware that this can be done with simple string formatting, however, this is not very flexible, so if something gets passed in that I don't expect, the string formatting could fail. It's simply more prone to issues.
I want to do this dynamically instead. Here's what I've tried.
Attempting to EnsureUser with the claims identifier above, then calling SPUser.Name:
SPUser spUser = SPContext.Current.Web.EnsureUser(spUserName);
userName = spUser.Name;
I've tried the following strings as a parameter in EnsureUser, all result in an exception: The user with the specified logonName cannot be found in Active Directory.
0e.t|saml provider|first.last#domain.local
saml provider|first.last#domain.local
first.last#domain.local
Again, all of those fail.
Another approach I tried, using SPClaimProviderManager (pulled from this blog):
SPClaimProviderManager mgr = SPClaimProviderManager.Local;
if (mgr != null && SPClaimProviderManager.IsEncodedClaim(userName))
{
spUserName = mgr.DecodeClaim(SPContext.Current.Web.CurrentUser.LoginName).Value;
}
I want to ensure that I'm attempting to decode an actual claim, and not something else, so I call IsEncodedClaim. This, however, always returns false.
My questions:
1) What am I doing wrong here that results in both of these attempting failing? What do I need to do differently for them to function properly?
2) Is there a better method to get a friendly claims user name without string parsing?
sigh Somehow the i: at the beginning of the claims string was being lopped off.
Should have read i:0e.t|saml provider|first.last#domain.local. Once that was added back, everything started functioning properly.

Categories

Resources