Setting the Manager Field in Active Directory
One thing I like to do in Active Directory is set the Manager field. To be honest, I’m not sure why I do this because we’re not using it, it’s just something I do. I guess you could call it future proofing. But there is a problem with this and that’s what do you do when a Manager leaves the company? There’s no easy way to pick up their direct reports and transfer them to a new manager. Until now.
The Manager Field and Why It Sucks
In Active Directory Users and Computers (ADUC) it’s pretty easy to set who a person’s manager is and if that person is a manager you can see their direct reports from the same tab. But Active Directory doesn’t actually store those relationships, ADUC is simply doing a query against your AD for all of the people who have the user you’re opening in their Manager field. And if you delete that Manager in AD? Poof! All of those direct reports disappear.
Of course you could write those direct reports down, then edit each person and manually change the manager before you delete the person who left but that would be pretty painful, and isn’t that exactly what Powershell is meant to solve?
Another reason it’s not the greatest mechanism in the world is the field only shows who the manager of that user is. No other relationships exist and if a person reports to more than one person there is simply no way to represent that.
The SAADManager
When making any kind of function, especially one you intend to release in the wild–and your intent is have it behave like a cmdlet–you need to be careful to not step on any existing cmdlet’s. Not to mention future ones too, which is challenging. The standard I’m seeing out in the wild is to use a standard verb then put some identifier just before the noun. A great example of this is Quest’s tools all start with a Q, like
Get-QADUser Get-QADComputer
And so on. So when Microsoft finally released their AD tools there was no conflict. I ran into this problem when helping someone troubleshoot a script for their vRanger product. They were using Start-Job which is the same cmdlet for submitting background jobs! Boy was that confusing for a while! The other problem is the vRanger cmdlets were outputting text instead of objects so a lot of the standard technique’s just weren’t working (but that’s another story).
Anyway, I wanted to make sure my functions stayed unique so I decided to use SA, for the Surly Admin. But when you combine that with AD and Manager it made a fun acronym, SAADManager. Love it when a plan comes together!
Set-SAADManager
Before we can move direct reports we need a way to set them in the first place. You can always use ADUC, of course, but we need a way to do this quickly and easily. Especially for testing! Hence Set-SAADManager was born. This function takes user input from the pipeline–from multiple sources–and assigns these users to whatever manager you assign with the -NewManager parameter. I also wanted to give the function the same range of options that any cmdlet has, so that meant support -WhatIf, -Verbose and -Confirm. This took advantage of the techniques I’ve built up here and here.
Here are a couple of examples of how you could use Set-SAADManager:
Set-SAADManager -Users "tsk","tsw" -NewManager tsa Set-SAADManager -Users (Get-Content users.txt) -NewManager tsa Get-ADUser -Filter { SamAccountName -like "ts*" } | Set-SAADManager -NewManager tsa Get-ADGroupMember TestGroup2 | Set-SAADManager -NewManager tsa
As you can see, there are a lot of different ways you could do this. But when I was doing it my office, I found myself using example #1 as it was just the easiest and quickest way of getting the job done. It helps that my usernames are easy to figure out (first initial, last name) as opposed to some places that use some other system. I once had a user name of S195–anyone remember SLIMS?
Clear-SAADManager
Runs much like Set-SAADManager but is dedicated for clearing out the manager field entirely. Probably not a lot of use for this except in the testing phase, but I had it so included it in the module.
Move-SAADManager
This function was the primary reason for the entire module. As I mentioned above, if you delete a manager all of the direct reports lose their connection to that manager and suddenly a part of your organization is no longer configured. Using this function you can now move all direct reports of an exiting manager and assign them to another manager.
Future functionality would be to create a “placeholder” account. Most of the time a replacement manager is not in place so moving the direct reports is difficult so having the script create a placeholder account to temporarily hold onto those direct reports for you. Then when you move the users off the placeholder account later it will delete the account after.
Get-SAADManager
This is the reporting functionality of SAADManager and outputs two report types. First is a standard Powershell Object with all of the information you need in it. I wanted this kind of output so you could manipulate and use it anyway you wanted, whether it be an HTML report that you email to executives or something you feed into another script for building a Visio organization chart or whatever you want.
The second output type is a HTML report that uses a Google visualization for organization charts. It’s a really simple method for creating a graphical web page of your organization. The output comes out as plain text so you will have to pipe it into Out-File to save it. I’m a bit torn on this one because I wanted to give you the most flexibility with what to do with the output but maybe just saving it to a file for you is the best way. Feedback in comments on this would be helpful.
Here’s an example of what the organization chart looks like
The user’s title will displayed in red under their name, and if you hover over the node it will show you their telephone number.
Of course, nothing comes without some kind of problem. I knew for a fact that my HR Manager would want to print this out and that’s where I ran into a major snag. The Google visualization simply won’t print properly. Since my org chart at work is much larger it scrolls way over to the right, but when printing it chops the visualization at the page break and that’s it, it doesn’t print additional pages that you can paste together–which I think would have been acceptable. No fix for this, but if you know something please let me know!
For future functionality my intention is to add the ability to target a manager and the script will do a straight line up to the CEO and then down and out on everything underneath. This would give you the ability to “fit” a org chart on one page depending on where you target the chart. Not a perfect fix but it would work.
The SAADManager Module
All of these functions were rolled up into the SAADManager.PSM1 file that you can load before you use the functions. Once loaded you can use the standard Powershell Help commands to get additional information about each function, including many more examples.
Download the Module here at Spiceworks and save it as SAADManager.PSM1. The path can vary based on how much you think you will use the module. You could load it by using the full path:
Import-Module c:\scripts\SAADManager.PSM1
You can also save the module in the default locations, of which there are two:
$env:PSModulePath
This will reveal two different locations by default:
C:\Users\martin.SURLY\Documents\WindowsPowerShell\Modules C:\Windows\system32\WindowsPowerShell\v1.0\Modules\
The first path is your personal module path, while the System32 path is for anyone who may log into your computer. If you save SAADManager.PSM1 file in either location you can then load it by typing:
Import-Module SAADManager
There you have it, the full SAADManager module with the ability to dynamically create org charts straight off of your Active Directory. Next post I want to talk about Hashtables and Powershell Objects, which is something that came up while creating the Get-SAADManager reports.
Thank you for this, I was about to write a module like this to deal with managers. I hadn’t heard of Google Visualization but it will definitely be useful, I was going to look for a visualization back-end for a pet project on a GUI of the AD topology. Cool stuff
[…] field in Active Directory must be properly set and maintained for this data to be useful. See my Manager Maintenance module for help there! You can also use the Department field which is keyed directly off of Active […]
Thanks for this note. I’ve decided to use it and I’m trying to pipe information from the Get-ADUser cmdlet (searching for users in a specific OU) and I keep getting “Set-SAADManager : Cannot bind argument to parameter ‘Users’ because it is an empty array.” Here is the command I’m using:
PS C:\> Get-ADUser -Filter * -SearchBase “ou=Other,ou=All Users,dc=local” | Set-SAADManager -NewManager new.user
Thoughts?
SAADManager isn’t getting any data, hence the failure. The trick is to perfect your Get-ADUser first. On the surface it looks like:
Get-ADUser -Filter * -SearchBase “ou=Other,ou=All Users,dc=local”
Is not finding anything. Try running that alone and seeing what you get. You can also add this parameter to make sure the sub-OU’s get searched: -SearchScope Subtree
The command as is provides me all the users I’m looking for.
Another note, it gives me this error for as many user accounts it is trying to modify.
Can SAADManager be used to set the manager attribute for computer objects also?
No, sorry, user objects only.
I’m attempting to rewrite it using Get-ADComputer as a substitute for Get-ADUser. Will post if I get it to work.
Nice! I look forward to seeing it!
I have it if you’re interested. Only hitch was the fact that ADUser uses the parameter -manager whereas ADComputer uses -ManagedBy. Got it work though.
Sure, send me the zip: martin@pughspace.com
[…] is only a single value so no goofy ForEach looping. I’ve actually covered Manager before here (and a few other places), so here’s what our calculated field would look […]
Martin,
Would you have a solution that would synchronize the Manager field from a source domain and bring the property over to the target domain. I am working on a migration project to create/synchronize user objects from the source domain. I am using a tool that works well, but the Manager property is not coming over. Looking for a script that I could schedule and run daily to ensure the Manager field is synchronized over to the target domain. Have you ever been had to deal with this?
That would be a bit harder Anthony. I’d get the user object of the Manager in the primary domain, which would get me the DisplayName. From there I would go over to the other domain and Get-ADUser on the name and get the user object on the new domain, then you can get the distinguishedName from that and apply THAT data to the user object in the new domain.