Provisioning users in Active Directory with PowerShell and the QAD cmdlets

As part of the EnergizeIT tour that I was on for the past three weeks, I did a quick introduction to PowerShell and then showed how the ability to automate tasks using PowerShell can make the job of an IT administrator much, much easier.  The scenario for the automation example I used was this: your HR department contacts you on Friday afternoon and tells you there are a bunch of new users coming in next week and you need to make the accounts right away.  The actual number is arbitrary because PowerShell scripts are the same for 1 user as they are for 1000000 users (exaggerated as that might be), but for my example I used a dozen users.

The point with this example was to show you how you can accomplish a task like this quickly regardless of the number of users being created and go home on time for date night, your son’s baseball game, etc.  This demonstration was very well received, and at the end of the demonstration I promised that I would post the script I wrote during the demo here in my blog.  The script that I post here may look slightly different from the script you saw me run at your tour event because I wanted to make sure shared the answer to a question someone asked me during the tour: How do I set the password for the new users when I create them?

For those of you who didn’t see the live demonstration, note that the csv file I used (C:\Users\Poshoholic\Documents\NewHires.csv) contained the following text:

FirstName,LastName,Title
Dmitry,Prosser,Software Developer 4
Oisin,Hill,Quality Analyst 1
Jeffrey,Shell,Senior Support Representative
Don,Munro,Software Developer 1
Charlie,Shaw,Project Manager
Marco,van Oursow,HR Assistant
Brandon,Russel,Product Manager
Keith,Hicks,Software Developer 3
Marc,Grehan,Product Marketing Manager
Karl,Jones,Quality Analyst 3
Kirk,Lee,Quality Analyst 1
Thomas,Sotnikov,IT Analyst 2

(FYI: if you think those names look familiar, I took the first names and last names of 12 PowerShell MVPs and mixed them up)

During the demonstration, the script below was built up iteratively within the PowerShell console so that you could see the thought process involved in creating a script that way.  In this blog post however, I’m simply going to post the finished script.  If you have questions about the demonstration or want to refresh your memory on how you could build a script like this iteratively, let me know.  The finished script to create the users from the csv file simply looks like this:

Import-Csv C:\Users\Poshoholic\Documents\NewHires.csv `
    |
Add-Member -Name Name -MemberType ScriptProperty -Value {$this.FirstName + + $this.LastName} -PassThru `
    |
Add-Member -Name SamAccountName -MemberType ScriptProperty -Value {($this.FirstName[0] + $this.LastName.Replace( ,)).SubString(0,20)} -PassThru `
    |
New-QADUser -City Ottawa -UserPassword P4$$w0rd -ParentContainer poshoholicstudios.com/users

Please note the following if you want to use this as a basis for your own script:

  1. You can copy this script from my blog and paste it directly into the PowerGUI Script Editor where you can customize it to meet your needs (be careful of the word wrap – there should be four lines of script once you paste it in PowerGUI).  Alternatively if you want the script already in a ps1 file, you can download it here.
  2. This example requires the Quest AD cmdlets to create the new users.  Once you have those installed, don’t forget to load them in PowerShell using Add-PSSnapin or in PowerGUI using Libraries in the File menu.
  3. This shows the finished script I built during the demonstration, with the addition of the assignment of the default user password value as P4$$w0rd.  Whatever you use for the default password value, it must meet your password requirements in your lab.
  4. If you want to run this without making changes, don’t forget to append -WhatIf at the end of the last line in the script.

Don’t be afraid to ask me questions about any of this, whether you need help customizing this script to make it work in your environment or just want an explanation of how the script works.  I’m always happy to help!

Kirk out.

Share this:

Essential PowerShell: Learn how to find what you are looking for

As silly as this may sound, learning how to find what you’re looking for in PowerShell is key if you want to learn PowerShell quickly and easily.  PowerShell is a rather unique language in that most of the information you will need to use the language is retrievable by using the language itself.  The problem for newcomers to PowerShell who like to dive right in when learning something and who don’t want to read through lots of documentation to get started is that they need to know some PowerShell to learn more about PowerShell and what it can do.

When I first started learning PowerShell I was fortunate to be able to see PowerShell presented twice, both times by Jeffrey Snover, the “father” of PowerShell.  In both presentations as he wrapped things up he mentioned that if there’s one thing you should make sure that you take with you about PowerShell it’s a set of five cmdlets that are key to learning more about PowerShell.  They are (in no particular order): Get-Help, Get-Command, Get-Member, Get-PSDrive and Get-Alias.

Rather than pulling the documentation about these cmdlets into this article, I thought it would be more useful to follow the KISS principle and list a series of questions you might ask yourself about PowerShell accompanied with the PowerShell script (mostly one-liners) that can be used to answer those very questions primarily using the cmdlets I mentioned above.  Here are the questions and their answers to help get you started.

I’ve heard PowerShell cmdlets all follow a verb-noun syntax.  What verbs are available in PowerShell?

Get-Command -CommandType Cmdlet | Group-Object -Property Verb -NoElement

What cmdlets use the verb “out”?

Get-Command -Verb Out

What cmdlets use the noun “command”?

Get-Command -Noun Command

What examples are available for the Tee-Object cmdlet?

Get-Help Tee-Object -examples

What is the full help information for Tee-Object?

Get-Help Tee-Object -Full | Out-Host -Paging
# Note: I could have replaced “Out-Host -Paging” with “more” and the result would have been the same

What are the non-common parameters of Set-Location (with their documentation)?

Get-Help Set-Location -Parameter *

What cmdlets have a parameter like “path”?

Get-Help * -Parameter *path* | Sort-Object -Property Name

What general PowerShell help topics are available?

Get-Help -Category HelpFile,Provider

I need general help on operators.  Where can I find that information?

Get-Help -Category HelpFile,Provider | Where-Object { (Get-Help $_.Name | Out-String).Contains(“operator”) }

Now that I see the help topics and providers that reference the keyword “operator”, how do I see the details?

Get-Help about_operator
Get-Help Variable
# etc.

What aliases are defined for the ForEach-Object cmdlet?

Get-Alias | Where-Object {$_.Definition -eq “ForEach-Object”}

I’ve heard PowerShell even treats the registry as a drive.  What other drives are there?

Get-PSDrive

How do I start browsing the Registry in PowerShell?

Set-Location HKLM: # or cd HKLM:
Get-ChildItem # or dir
Set-Location Software # or cd Software
# etc.

I noticed that there is a drive for environment variables.  How do I use that to check the value of my Path environment variable?

(Get-Item env:Path).Value

How do I add all of my installed PowerShell snapins to the current session so that I can use their cmdlets too?

Get-PSSnapin -Registered | ForEach-Object { if ((Get-PSSnapin $_.Name -ErrorAction SilentlyContinue) -eq $null) { Add-PSSnapin $_.Name } }

(Note: More useful one-liners using Get-PSSnapin can be found here.)

I need to enumerate a bunch of services and then do other things.  Since these are enumerated as objects, how can I tell what I can do with them (i.e. how can I tell what properties and methods they have)?

Get-Service | Get-Member

Are there other basic questions that you think should be on this list?  After learning how to find the information you need within PowerShell, what has been your biggest stumbling block?  Let me know in the comments!

Kirk out.

Technorati Tags: , , , ,

Get-PSSnapin one-liners

With the number of PowerShell snap-ins that are available continuing to grow steadily, I’ve noticed more and more that people are looking for ways to determine if a snap-in was properly registered, whether snap-in changes are properly showing up in the PowerShell console, and answers to other general snap-in troubleshooting questions (note, a PowerShell snap-in is also referred to as a PSSnapin within the PowerShell console).  Fortunately, as is the nature with many things in PowerShell, there are a number of one-liners that we can use to gather information about snap-ins or to diagnose and troubleshoot snap-in problems.  I’ll list each one with the question that it was designed to answer below.

What snap-ins come with PowerShell?

Get-PSSnapin `
    | Where-Object { $_.IsDefault -eq $true }

What third-party snap-ins do I have on this system?

Get-PSSnapin -Registered

Which of the third-party snap-ins are already added to my current PowerShell session?

Get-PSSnapin `
    | Where-Object { $_.IsDefault -eq $false }

Which of the third-party snap-ins are not added to my current PowerShell session?

Get-PSSnapin -Registered `
    | Where-Object { (Get-PSSnapin $_.Name -ErrorAction SilentlyContinue) -eq $null }

How can I see all snap-ins and identify which ones come with PowerShell, which ones are third-party, which ones are added to my current PowerShell session and which ones are not (i.e. how do I put all of this information together)?

(Get-PSSnapin | Where-Object {$_.IsDefault -eq $true}) + (Get-PSSnapin -Registered) `
    | Add-Member -Force -Name IsAdded -MemberType ScriptProperty -Value {(Get-PSSnapin $this.Name -ErrorAction SilentlyContinue) -ne $null} {} -PassThru `
    | Format-List -Property Name,IsDefault,IsAdded,PSVersion,Description

I’m having general issues when using a third-party snap-in (cmdlets I’m trying to use aren’t found, changes made in a new version aren’t showing up in PowerShell, etc).  The snapin is called ProblematicSnapin.  How can I find out detailed information about the snap-in itself so that I can verify the information about the snap-in in PowerShell and troubleshoot the issues?  Note that for this one-liner you must replace “ProblematicSnapin” with the name of the third-party snap-in you are using.

Get-PSSnapin -Registered -Name ProblematicSnapin `
    | Add-Member -Force -Name IsAdded -MemberType ScriptProperty -Value {(Get-PSSnapin $this.Name -ErrorAction SilentlyContinue) -ne $null} {} -PassThru `
    | Format-List -Property *

What cmdlets are provided by a snap-in?  Note that for this one-liner you must replace “SnapinName” with the name of the snap-in you are inquiring about.  Also note that this only works for default snap-ins and snap-ins that have been added to the current PowerShell session.

Get-PSSnapin -Name SnapinName `
    | ForEach-Object { Get-Command -PSSnapin $_ } 

Hopefully these one-liners will help you get answers to your PSSnapin related questions.

Enjoy!

Kirk out.

Technorati Tags: , , , , ,

Essential PowerShell: Know your system variables

By default PowerShell v1.0 comes with 44 variables preinstalled.  Some of these variables are used to configure the maximum number of objects that PowerShell supports, others are used to configure output preferences for scripts, and there are more with many other purposes.  As a script author, it is very useful to understand what the variables are used for so that you can take advantage of them in your scripts.

Fortunately, the wonderful folks at Microsoft who created PowerShell embedded tons of help documentation about PowerShell directly within the shell.  So learning what variables are used for is simple as long as you know how to get the information (which isn’t always that simple for newcomers).

Here’s a useful one-liner that can be used to produce a detailed list of all PowerShell variables.  The output includes the variable name, type, description, value, and options set on the variable.  It also includes a custom member called DisplayValue which is a more detailed view of the data that the variable contains.  Here’s the one-liner, split across multiple lines to improve readability:

Get-ChildItem -Path Variable: `
       | Add-Member `
              -Name Type `
              -MemberType ScriptProperty `
              -Value { $this.GetType().FullName } `
              -PassThru `
       | Add-Member `
              -Name DisplayValue `
              -MemberType ScriptProperty `
              -Value { (Get-Variable -Name $this.Name -Scope 1 -ValueOnly | Format-List -Property * | Out-String).Trim("`r`n") } `
              -PassThru `
       | Sort-Object -Property Name `
       | Format-List -Property Name,Type,Description,Value,DisplayValue,Options `
       | Out-Host -Paging

For the most part, the output of this one-liner provides enough of a description for each variable to explain what it is used for.  Some variables that don’t have descriptions are easily understood by looking at their DisplayValue.  A few might be confusing though.  The $ variable (which you would use in your script as $$) contains the last token in the last command that was run.  The ^ variable ($^ in your script) contains the first token in the last command that was run.  The error variable ($error) contains the history of errors encountered during the current PowerShell session.  You can clear this history at any time by running the $error.Clear() command.

If you are authoring a PowerShell extension (an extension may be a PowerShell snapin, a set of functions, PowerShell scripts, etc) and if your extension adds additional global variables that will be useful to consumers of your extension, I strongly encourage you to provide enough details in the variable description that PowerShell continues to be a self-documenting scripting environment.  The self-documenting nature of PowerShell is unique and incredibly beneficial to PowerShell users.  Please continue to promote this through your own PowerShell work.

If there are any system variables that you are having a hard time with, or that you feel I should have described in more detail in this post because they just aren’t intuitive, feel free to let me know in the comments and I’ll help you out as best as I can.

Kirk out.

Technorati Tags: , , ,

Nobodys perfect

While PowerShell is by far the best 1.0 release I have worked with in a really long time, it isn’t without its faults.  Today I was trying to figure out if it was possible to programmatically get the type(s) of the object(s) that will be returned from a cmdlet without running that cmdlet.  So far I haven’t been successful, but while exploring I came across a big inconsistency in the current embedded documentation for PowerShell cmdlets.

Take at look at this script:

Get-Command -commandType cmdlet `
    | Add-Member -passThru -name returnType -memberType ScriptProperty -value `
        { (Get-Help $this -full).ReturnValues.ReturnValue.Type.Name } `
    | Add-Member -passThru -name returnTypeDescription -memberType ScriptProperty -value `
        { `
            $description = (Get-Help $this -full).ReturnValues.ReturnValue.Type.Description | out-string; `
            if ($description -ne $null) { $description.Replace(“`r`n”,“”) } `
        } `
    | Format-Table -property name,returnType,returnTypeDescription

This script will get all cmdlets, add two properties to those cmdlets (the return type and the return type description, as extracted from the help documentation), and then output a table with the cmdlet name, the return type and the return type description.  The results, well, they leave a lot to be desired. 🙂

Since the get-help cmdlet only shows the return type and not the return type description in the help documentation it generates, usually the information about the return type is either partially missing or completely missing.

Hopefully this will get cleaned up in a future release of PowerShell.

Oh, and if someone out there knows how to programmatically determine the return type of a cmdlet without calling it and wants to share that knowledge through comments, that would be swell. 🙂

Kirk out.

Technorati Tags: , ,