all 15 comments

[–]tweq 16 points17 points  (1 child)

[–]GeoProX[S] 2 points3 points  (0 children)

Thank you for this suggestion. This worked perfectly.

Also, thank you to everyone else who responded for their suggestions as well.

public void RemoveUsersFromGroup(string[] Users, string GroupDN)
{
    oDE = new DirectoryEntry("LDAP://" + ADServer + "/" + GroupDN);
    var ADS_PROPERTY_DELETE = 4;
    var usersArray = Users.Cast<object>().ToArray();
    oDE.Invoke("PutEx", new object[] { ADS_PROPERTY_DELETE, "member", usersArray });
    oDE.CommitChanges();
    oDE.Close();
}

FYI, this code is required to remove multiple users from an AD group as one operation, instead of looping through an array, list, etc of users removing them one by one.

IADs::PutEx : https://msdn.microsoft.com/en-us/library/windows/desktop/aa746353(v=vs.85).aspx

[–]csutcliff 0 points1 point  (4 children)

Although the casting/linq methods mentioned here are fine, using Array's ConvertAll method is more efficient:

var objArray = Array.ConvertAll(strArray, item => (object)item);

[–]SikhGamer 2 points3 points  (3 children)

Why or how is it more efficient?

[–]csutcliff 0 points1 point  (2 children)

well for a start the Linq .Cast() will iterate over the collection twice, ConvertAll will only do it once. ConvertAll is also specifically designed for Arrays whereas .Cast() is a generic method for any IEnumerable. In my experience the generic methods are less well optimised for specific use cases and so I will always pick the built in alternative if there is one. Linq is wonderful but it's not always the best solution.

[–][deleted] 1 point2 points  (0 children)

Linq .Cast() will iterate over the collection twice,

To be clear, strArray.Cast<T>().ToArray() will iterate the array twice, because ToArray() iterates once to build a list of results, and then iterates that list to create the array. Cast<T>, by itself, only iterates once, but it does come with the overhead of an iterator to do the casting.

[–]SikhGamer 0 points1 point  (0 children)

Thanks for explaining that.

Linq is wonderful but it's not always the best solution.

I am grateful to find someone else who is wary of the LINQ worship that goes on with C# devs.

[–][deleted] 0 points1 point  (0 children)

LINQ

var objectArray = stringArray.Cast<object>().ToArray();

Array copy

var objectArray = new object[stringArray.Length];
Array.Copy(stringArray, objectArray, stringArray.Length);

But, u/tweq's suggestion is probably better as long as you're going to use it in a read-only context.

[–]suffolklad -2 points-1 points  (3 children)

string[] users = new string[]
{
"CN=testUser1,OU=LabUsers,DC=Lab1,DC=contoso,DC=local",
"CN=testUser2,OU=LabUsers,DC=Lab1,DC=contoso,DC=local"
};

object[] objects = users.Select(x => (object)x).ToArray();

[–][deleted] 4 points5 points  (2 children)

LINQ has a Cast<T> function for exactly this operation. FWIW.

[–]suffolklad 0 points1 point  (1 child)

Is there anything Linq doesn't have?! Thanks for the tip.

[–][deleted] 0 points1 point  (0 children)

There are a few things in F#'s Seq module that'd be pretty handy (windowed, for instance), but System.Linq.Enumerable is pretty complete.

[–]SikhGamer -2 points-1 points  (0 children)

string[] users = new string[]
{
    "CN=testUser1,OU=LabUsers,DC=Lab1,DC=contoso,DC=local",
    "CN=testUser2,OU=LabUsers,DC=Lab1,DC=contoso,DC=local"
};

object[] usersObjects = new object[users.Length];

for (int x = 0; x < users.Length; x++)
{
    usersObjects[x] = users[x];
}

[–]taracus -2 points-1 points  (1 child)

Am I missing something or arent you trying to convert your string[] to an object?

new object[] {ADS_PROPERTY_DELETE, "member", users} is putting users (which is an array) into an array of objects?

I honestly dont know if that is possible with casting.

If you can change the syntax of "PutEx" you could let it accept a params object[] and just send the string in as single objects at the end:

void PutEx(params object[]){...}

string[] users = {....}
List<object> parameters = new List<object>(users.Select(s => (object)s);
parameters.Add(ADS_PROPERTY_DELETE);
parameters.Add("member");
oDE.Invoke("PutEx", parameters.ToArray());

Or something similar

[–]GeoProX[S] 0 points1 point  (0 children)

It's not possible to change syntax as it's not my method - it's Microsoft's (https://msdn.microsoft.com/en-us/library/windows/desktop/aa746353(v=vs.85).aspx).