Skip navigation

Tag Archives: active directory

As a Systems Engineer/SCCM Administrator I spend a lot of time parsing through data, and assisting support technicians in tracking down failing assets.  Now mind you, I have plenty of reports that give me the information I need to identify the machine and users and techs responsible etc, but what happens when I get a random list of employee names from a project manager that has 0 access to user ids or asset numbers for machines?  Well, I have to find that information, then spend time later pointing them to resources I’ve made available for them; but that’s another topic….

Anyway, I face both problems, I’ll receive a list of userids or usernames and have to resolve them one against another.  Well thanks to powershell I’m able to do so quickly and easily through profile functions.  Now, I’ll explain the benefits of profile functions after the code below:


Import-Module activedirectory

Function Get-UserName {

Get-ADUser $USERID | select name
Set-Alias gun Get-UserName
Function Get-Userid {
$NAME = $NAME + “*”
    Get-ADUser -Filter {Name -like $NAME} | select samaccountname,name
Set-Alias guid Get-Userid


 How do I use profile functions?!?

Powershell, much like the BASH shell in Unix/Linux, has a profile “script” so to speak at startup.  There is a global one found at:

  • %WinDir%\System32\WindowsPowerShell\v1.0\Profile.ps1
  • %WinDir%\System32\WindowsPowerShell\v1.0\Microsoft.PowerShell_Profile.ps1
  • %WinDir%\System32\WindowsPowerShell\v1.0\Microsoft.PowerShellISE_Profile.ps1

The same filename syntax is used for the user profile versions:

  • %UserProfile%\My Documents\WindowsPowerShell\Profile.ps1
  • %UserProfile%\My Documents\WindowsPowerShell\Microsoft.PowerShell_Profile.ps1
  • %UserProfile%\My Documents\WindowsPowerShell\Microsoft.PowerShellISE_Profile.ps1

See a pattern?  Simple enough right?  None of these profiles exist by default though, they must be created.  The names are fairly indicative of what they control, but here’s a breakdown:

  • Profile.ps1
    • This governs startup of both the standard powershell, and the ISE.
  • Microsoft.PowerShell_Profile.ps1
    • This governs startup of the standard powershell console only.
  • Microsoft.PowerShellISE_Profile.ps1
    • This governs startup of the ISE powershell console only.

Simple enough right?  Now, for the sake of simplicity, lets build a current user version of the profile.ps1 and save the above code to it.  Make sure you’ve installed the activedirectory cmdlet module provided with windows 7. Now launch powershell and viola you should now have the cmdlets:

  • Get-UserName
  • Get-UserID

and their aliases:

  • GUN
  • GUID

Ok, now what?

Here’s the thing about profile functions.  You can treat them like cmd-lets now.  That also means that you can script against them.  Consider them a static variable for every powershell session that you have configured with this profile.

Pretty cool huh?  One of the most powerful features of the shell is it’s configurability, and profile functions and aliases are the tip of that spear.

In the case of user name capture, or id capture, I’m but a simple gc and for-each statement away from processing the list given to me.

I hope this helps broaden your practical understanding of profiles, and gets your creative juices flowing for building your own administrative tool kits.  Happy scripting.

So recently we had to perform an AD cleanup of aged computer objects in our environment.  For a lot of companies this is a pretty standard procedure, for others, it’s just ignored (as was the case for us for a while).

Anyway, in the course of completing this task we had looked at a few scripts and tools that others had written/published around the internet and I inevitably got the bright idea to sit and write a tool for us to use in PowerShell.  So I setup my goals and fired up the old editor and went to work.


  • Identify aged objects
    • To identify aged objects, I went with the PasswordLastSet property of the object. There really isn’t a much better one to utilize, and it works off a 30 day cycle so it’s close enough.
  • Write out data for records
    • For write out I built a switch (–report) that will utilize the export-csv cmdlet to export a record of machines to the current users desktop.
  • Move objects to different OU
    • For moving objects I used the Move-ADObject cmdlet from the activedirectory module available with win 7 and server 2008 features.
  • Generic (no non standard add ins)
    • To keep it generic I chose to use the activedirectory module since we are running on 2008 servers, and migrating to windows 7. This insures future state usage, and prevents additional downloads or installs for functionality.
  • Modular (sometimes you just want a report)
    • To keep it modular, I built the (-move) switch. Unless the user explicitly defines this then the script will only report what was requested. Either to console output, or to a csv on the desktop (-report).
  • Versatile for targeting object date ranges and OUs
    • To insure versatility, I left 3 variables to be declared. $TIME, $TARGETR, $TARGETM. Date range, target OU to read, and Target OU to move respectively.
  • Script initially with potential to integrate in profile as a function
    • To build it as a standalone script, I originally had a (-help) switch that would output similar information as the get-help blah-blah –examples. Now with it functionized, I’ve removed that and added an overall function name to the code.

How it works:

Once applied to the PowerShell profile it can be called using get-adinactivecomputer.  By default it requires a date range either specified in <number>d for days or <number>y for years and a target OU to search from.  If these variables aren’t applied at the command line the function will request them at run time.

If –move and –report are specified then the function will need a target OU to move the items to and will generate a list with Object names and PasswordLastSet dates on the desktop and attempt to move them to the specified OU.  The switches must be declared at the command line but all variables are requested at run time if not stated before hand.

Now the nuts and bolts…..


First we check for the $TIME variable and request if it’s not present, then insure it’s in string format.  We’ll check that string for a d or a y to determine how to handle the string and then convert it to an appropriate integer value.  We’ll also bailout if we can’t distinguish the range (since this is a has the potential of causing serious AD harm we want to insure the user is accurate in their input).

Second we’ll check for the –report switch and if it’s present we’ll run the internal ADCLEANUP function and pipe it to export-csv $home\desktop\inactivecomputers.csv.  If it’s not then we’ll just generate output to the console.  We pass the $TIME and $TARGETR variable to this function.

Third we check for the –move switch, and if it’s present run the internal function MOVEOLD and pass it the $TARGETM variable.

Fourth and final step, we nullify a global variable set during the ADCLEANUP function.



First step of the ADCLEANUP function is to insure the activedirectory module is loaded.  Next it verifies that a $TARGETR variable exists, if not it will prompt for one.  It then will take and search AD for the distinguished name of the OU provided. 

Next we build a date range variable using .Net Date Math.  We will subtract the total number of days by the integer value provided in $TIME from Today’s date and store that in $COMPARE. 

Now we declare a global variable $ADLIST that grabs all computer objects with PasswordLastSet property less than or equal to $COMPARE from the $TARGETR OU.

We then process those objects with a ForEach into a PSObject for reporting purposes specifying the Name and PasswordLastSet properties.  I did this mainly to guarantee a clean csv export.



The MOVEOLD function is fairly straight forward.  We check for the $TARGETM variable, if it doesn’t exist we prompt for an input.  We then build $TARGETM into a manageable string, then again we set it as a proper OU.  We run the $ADLIST through another ForEach statement and use Move-ADObject to relocate each $ITEM to $TARGETM.


I posted this script on the script center repository.  I didn’t build in any error catching which I should have, and plan to revisit that at a later date.  I enjoyed writing it so much I wanted to take some time to dissect it and discuss it a bit.  Hopefully this information proves useful to someone with similar goals and or general interest. 

For the the Microsoft.Powershell_profile.ps1 and Microsoft.PowershellISE_Profile.ps1 version of the script, perform the following steps in order:

Uncomment lines 4 and 193

Delete lines 7 through 50

Delete: ,[switch]$HELP from line 6

Delete line 46

Modify line 60 to read:                    `n`nTry get-help Get-InactiveADComputer -Examples`n";break}