Aug 01

PowerShell: get group membership using .NET

Hi All,

So recently I needed to get all the members of a group and all the members of the groups that a members of each of those groups… right on down the line. My head began to swim thinking about writting a function to get the members of one group, then degermine if a member was a user, computer, or another group, then getting the members of that group and so on, all while collecting the users in some form of global collection. really, it is messy!

Add to that, the fact that I don’t have a 2008 domain so everything here is of no value.

So, off I started my hunt and came across the .NET object GroupPrincipal in System.DirectoryServices.AccountManagement.

First thing I need to do is load the assembly so I have access to GroupPrincipal.

GroupPrincipal has a FindByIdentity method to get a group by name. But, the FindByIdentity requires a PrincipalContext.

PrincipalContext is defined as:

This says to me that it is some kind of logical grouping for where the FindByIdentity should be looking. Looking into the simplest of the contstructor for the PrincipalContext “PrincipalContext(ContextType)” says it requires a ContextType. The Context Type is an enum for Machine, Domain, or ApplicationDirectory. For what I’m doing, I want the Domain option.

So, in PowerShell I need to create a new ContextType object for the domain.

Then, I need to use that to find my starting group by identity (name).

Lastly, I need to get the members of the group

Well, that’s great, but it doesn’t give me all the members of the group! Looking at that GetMembers member, I can see there are two signatures. GetMembers() & GetMembers(bool recursive)! So now, instead of $group.GetMembers() |ft -auto, I can use $group.GetMembers($true) |ft -auto! and Poof! There is everyone in that group and that group’s groups straight on down the line!

Sweet!

Now, here it is in it’s entirety:

May 24

Sort PowerShell output by property name

Using the exchange command ‘get-mailbox’

or the single-line version…

–Gene

Feb 27

Exchange 2010 New-MoveRequest and the dumpster

So, you’re migrating from Exchange 200* to Exchange 2010 and you’re using the new fangled “New-MoveRequest.” You might have some questions about the dumpster. You know that thing that if the Admins could just get people to understand it, you would never have to restore from backup except for practice!

If you wanted to find out about New-MoveRequest, you might be tempted to go to the on-line help at New-MoveRequest. But there you wouldn’t find any information about the dumpster itself, only information about the command.

You may then find yourself at Understanding Move Requests which talks about alot of stuff about move requests. You may even find an area that talks about limitations in “Move-Mailbox” (Exchange 2007) which states “The Dumpster folder isn’t moved with the mailbox.” That’s all well and fine, but we want to know about the 2010 Move Request. A few lines down on that same Understanding Move Requests, you may find “Advantages of Move Requests” Where it doesn’t say anything about the dumpster. You might then assume that if it is a limitation in 2007, it must not be a limitation in 2010. And, you’d be right! In Exchange 2010, the New-MoveRequest will move the dumpster…

… if you’re moving from 2010!

If you’re moving from 200*. Sorry, no dumpste for you! Have a look at Troubleshooting Mailbox Moves under “The mailbox dumpster size exceeds the target quota.” A little ways down under “Resolution” you’ll find a line that says “Move requests don’t support moving an Exchange 2003 or Exchange 2007 dumpster to Exchange 2010.” That’s your answer!

Here is a blog entry from howExchangeWorks.com that spells this out quite clearly.

–Gene

Feb 17

Simplify creating a remote PowerShell connection (part 1)

For this example, I’ll be establishing a connection to Exchange 2010. My problem is that I’m lazy and that’s why I always script things out. the function is no different. Everytime I do this it’s the same process and if you’re like me, I usually have 4+ PowerShell windows open at a time. Using this function helps to make things easy for me.

When I do something multiple times I take out parts that change and they become variables in my script. Let’s look at a simple one-line command for creating a remote connection to (in this case) Exchange.

if you want to logon with different credentials you can runas PowerShell, or you can have New-PSSession prompt you using -Credential $(get-credential) in place of -Authentication kerberos like this:

With this second version of the command you get the GUI popup asking for your credentials and all subsequent Exchange commands will use these credentials.

So, in these two commands, the only thing that has changed is the $server variable and if you use remote powershell to Exchange, it doesn’t really matter which server you connect to. You may have a preference, based on server resources, but really it doesn’t matter. Although if you’re in New York I wouldn’t connect to the server in Australia!

Makin’ it easy!
So, to make my life easier, I do a dot-import of my ExchangeFunctions.ps1 file which has two things. the first thing it has is an array of preferred Exchange server names.

The second thing I have is a function called Get-Exchange2010PSSession. In this function, I have PowerShell do all the work and pick a random server for me. There is also a small optimisation that I’ll talk about later. Let’s get to the function…

Walk through
Walking through this function we start with the basic documentation. The first parameter $ServerList is a string array. This is the list we defined earlier in the exchangeFunctions.ps1 file. In the Begin { } section the $ErrorActionPreference is set to “Stop” This way our try { } catch{ } will work and we set what will become our resulting $session variable to a default of $null.

Within the process{ } section we start a do{ } until (condition) statement that will loop through the server list choosing a random server in the list. Remember, we will be getting the same set of commands from each server so it doesn’t really matter which server we connect to. Personally, I like to have the system choose a random server because I don’t want to get into the habbit of always running my code on the same system. Next is a try{ } catch { } block that does two things.

  1. Set the PowerShell Session Options with New-PSSessionOption. I’ll go over this later so we’ll skip this until the end.
  2. Create the new PS Session with New-PSSession using whatever the currently selected server.

If there is an error the function will echo it out in the catch { }. The function will continually try a different server untill $Session is successfully populated with a return from New-PSSession. Once that happens, Get-Exchange2010PSSession returns that $Session variable which you can import using Import-PSSession.

New-PSSessionOption
What about that New-PSSessionOption bit? Well, did you know the default time out for establising a session is 3 minutes? If you’re like me, you don’t want to wait that long. As a result, I setup my own PSSessionOption and set the time out to 30 seconds (30,000 miliseconds). I also set the culture. I don’t need to download the russian or chinese version of the commands, I don’t speak those languages. Using Get-UICulture I get the culture settings on the systems. The other two options probably don’t speed things up very much, but I like to think I’m sucking the marrow out of PowerShell with them. If you’re curious, check them out with

Next Time…
Next time I’ll show you how to make this even easier with an additional PowerShell functions that does ALL the work in setting up a remote PowerShell session

Jan 26

RBAC Helper #4 Who What Where for Role Groups

So, This is a drill down of information from a RoleGroup. With this script, you will be able to see Who is a member of the RoleGroup, What Commands The RoleGroup can run, and Where they can run them.

Jan 18

Get a count of mailboxes by Exchange 2010 database

Results:

Dec 23

RBAC Helper #2

So, we got the role entries for the management role, let’s now find out what management roles have a specific role entry. Basically, this is the revers of RBAC Helper #1.

Update 03/22/2012: I’ve updated this script due to changes in the way the Role Entries are presented.

Dec 01

Get 1 user from each database on an Exchange 07 server

Needed to test searching in some databases so I needed one user from all the databases on one server…

Aug 11

RBAC helper

Quick way to get all the Management Role Entries in a Management Role. Think of it as getting a list of what a Management Role is cappable of.

Jul 20

get all Exchange Servers and their IP addresses…

As one line:

Readable:

–Gene