/\/\o\/\/ PowerShelled

This blog has moved to http://ThePowerShellGuy.com Greetings /\/\o\/\/
$AtomFeed = ("Atom.xml")
$PreviousItems = (" Windows PowerShell Video: Next Generation Command ... "," PowerShell and Active Directory Part 5 "," PowerShell and Active Directory Part 4 (TypeData) "," PowerShell and MOM2005 part 2 : Updating Settings "," PowerShell Boolean FileMode "," Working with Fixed Length delimited Text files in ... "," PowerShell and Active Directory Part 3 (UserProper... "," PowerShell and MOM 2005 "," PowerShell and Active Directory Part 2 "," PowerShel and Active Directory Part 1 "," ")

Monday, August 07, 2006

 


PowerShell and Active Directory Part 6



In this part sixth part of the AD series we will make a start of the script to import / create users from a CSV file (template generated in part 5 of this series).

# Load the CSV file with users 

$newUsers = import-csv  C:\PowerShell\NewUsers.csv 

# the first user looks like this (see part 5)

PoSH>$newusers[0]


Name        : NewUser0003
displayName : Roberto  Tamburello
Description : Engineering - Roberto  Tamburello
Room        :
Telephone   :
FirstName   : Roberto
Initials    :
LastName    : Tamburello
Department  : Engineering
Company     :
HomeDir     :
HomeDrive   :
LogonScript :
Accountname : $222000-BOCQ2JHU74K1
Mail        : 


I will start by just echo-ing some of the properties to the screen in the first examples.
and I will start using a filter as we provide the objects on the pipeline :

# most Simple form Filter

filter new-AdUser {
  if ($_.Name) {"CN=$($_.name)"Else {throw "Name is Mandatory"}
}

# Check on the Name Property

PoSH>"foo" | new-AdUser
Name is Mandatory
At line:2 char:45
+   if ($_.Name) {"CN=$($_.name)"Else {throw  <<<< "Name is Mandatory"}

# if objects in pipeline have name property

PoSH>$newusers | new-AdUser
CN=NewUser0003
CN=NewUser0009
CN=NewUser0011
CN=NewUser0012
CN=NewUser0267
CN=NewUser0270


we will later switch to a function for this but I will start with a filter to show the difference

in this first filter you can see that $_ contains the current item and we can access the different field from the CSV file from the object, in this case we just echo it to the screen.

as we have seen in the second part of this series, all we really need to create a User is a CN, but we have also seen that the SamAccountname another mandatory property gets generated in that case and that that is not realy handy, as we most of the time want this the same as the CN name lets add a check for the property and if it's not there lets add it.

# added SamAccountname

filter new-AdUser {
  # check for name field :

  if ($_.Name) {"CN=$($_.name)"Else {throw "Name is Mandatory"}

  # If accountname is not given make it same as CN

  if ($_.Accountname) {"SamAccountName = $($_.Accountname)"Else {"SamAccountName = $($_.name)"}
}

# objects in pipeline have accountname property

PoSH>$newusers | new-AdUser

CN=NewUser0003
SamAccountName = $222000-BOCQ2JHU74K1
CN=NewUser0009
SamAccountName = $822000-KK9G22LQPGJV
CN=NewUser0011
SamAccountName = $A22000-RFN1CV2D2U5N
CN=NewUser0012
SamAccountName = $B22000-L10CLJU1NCSO
CN=NewUser0267
SamAccountName = $AA2000-R7OSI41L9LHR
CN=NewUser0270
SamAccountName = $DA2000-7UPIT07U0FPV 

# Remove accountname property 

PoSH>$newUsers |% {$_.accountname = ""}

# Now the SamAccountname will be generated the same as the CN

PoSH>$newusers | new-AdUser

CN=NewUser0003
SamAccountName = NewUser0003
CN=NewUser0009
SamAccountName = NewUser0009
CN=NewUser0011
SamAccountName = NewUser0011
CN=NewUser0012
SamAccountName = NewUser0012
CN=NewUser0267
SamAccountName = NewUser0267
CN=NewUser0270
SamAccountName = NewUser0270


As you can see, you can use this to keep the CSV file simple but extendable (you don't need to provide the samaccountname if you want it to be the same as the CN, but you CAN provide it if this is not the case ).
also as my exported users had generated samaccountname properties, I did clear them all so the samacountnames will be the same as the CN.

now to create the users we also need the the OU where to import the user, I will add this as a parameter to the function, but also make a check for a OU field in the CSV file to overrule this on a per user base.
also I will show some examples of how the OU gets parsed so you can use an OU object or the LDAP string :

# OU to import parameter

PoSH>[System.DirectoryServices.DirectoryEntry]$ImportOu = $mowOu
PoSH>[System.DirectoryServices.DirectoryEntry]$ImportOu = "OU=MowOu,DC=mow,DC=local"
PoSH>$ImportOu
out-lineoutput : Exception retrieving member "ClassId2e4f51ef21dd47e99d3c952918aff9cd": "Unspecified error
"

# LDAP path to import parameter

PoSH>[System.DirectoryServices.DirectoryEntry]$ImportOu = "LDAP://OU=MowOu,DC=mow,DC=local"
PoSH>$ImportOu

distinguishedName
-----------------
{OU=MowOu,DC=mow,DC=local}

#  list possible constuctors

PoSH>[System.DirectoryServices.DirectoryEntry].GetConstructors() |% {"$_"}
Void .ctor()
Void .ctor(System.String)
Void .ctor(System.String, System.String, System.String)
Void .ctor(System.String, System.String, System.String, System.DirectoryServices.AuthenticationTypes)
Void .ctor(System.Object)
PoSH>[System.DirectoryServices.DirectoryEntry]$ImportOu = "LDAP://OU=MowOu,DC=mow,DC=local"
PoSH>$ImportOu

distinguishedName
-----------------
{OU=MowOu,DC=mow,DC=local}

# Take care the LDAP path is CaseSensitive 

PoSH>[System.DirectoryServices.DirectoryEntry]$ImportOu = "LDaP://OU=MowOu,DC=mow,DC=local"
PoSH>$ImportOu
out-lineoutput : Exception retrieving member "ClassId2e4f51ef21dd47e99d3c952918aff9cd""Unknown error (0x80005000)"
PoSH>

# added OU as parameter and as field to the filter

filter new-AdUser ([System.DirectoryServices.DirectoryEntry]$importOU){
  # check for name field :

  if ($_.Name) {"CN=$($_.name)"Else {throw "Name is Mandatory"}

  # If accountname is not given make it same as CN

  if ($_.Accountname) {"SamAccountName = $($_.Accountname)"Else {"SamAccountName = $($_.name)"}

  if ($_.OU) {"OU = $($_.OU)"Else {"OU = $($ImportOU.distinguishedName)"}

}

# output now looks like this :

PoSH>$newusers | new-AdUser $mowou
CN=NewUser0003
SamAccountName = NewUser0003
OU=MowOu,DC=mow,DC=local
CN=NewUser0009
SamAccountName = NewUser0009
OU=MowOu,DC=mow,DC=local
CN=NewUser0011
SamAccountName = NewUser0011
OU=MowOu,DC=mow,DC=local
CN=NewUser0012
SamAccountName = NewUser0012
OU=MowOu,DC=mow,DC=local
CN=NewUser0267
SamAccountName = NewUser0267
OU=MowOu,DC=mow,DC=local
CN=NewUser0270
SamAccountName = NewUser0270
OU=MowOu,DC=mow,DC=local

# Some extra tricks using select like in part 5 of this series

# using select to add the OU property on the fly

PoSH>$newusers | select *,@{e={"OU=MowOtherOU,DC=mow,DC=local"};name='OU'} | new-adUser
CN=NewUser0003
SamAccountName = NewUser0003
OU = OU=MowOtherOU,DC=mow,DC=local
CN=NewUser0009
SamAccountName = NewUser0009
OU = OU=MowOtherOU,DC=mow,DC=local
CN=NewUser0011
SamAccountName = NewUser0011
OU = OU=MowOtherOU,DC=mow,DC=local
CN=NewUser0012
SamAccountName = NewUser0012
OU = OU=MowOtherOU,DC=mow,DC=local
CN=NewUser0267
SamAccountName = NewUser0267
OU = OU=MowOtherOU,DC=mow,DC=local
CN=NewUser0270
SamAccountName = NewUser0270
OU = OU=MowOtherOU,DC=mow,DC=local

# or combine the standard OU with some overruled users


PoSH>$newusers | select *,@{e={if ($_.name -eq 'NewUser0270'){"OU=MowOtherOU,DC=mow,DC=local"else {""}};name='OU'} | new-adUser $mowOU

CN=NewUser0003
SamAccountName = NewUser0003
OU = OU=MowOu,DC=mow,DC=local
CN=NewUser0009
SamAccountName = NewUser0009
OU = OU=MowOu,DC=mow,DC=local
CN=NewUser0011
SamAccountName = NewUser0011
OU = OU=MowOu,DC=mow,DC=local
CN=NewUser0012
SamAccountName = NewUser0012
OU = OU=MowOu,DC=mow,DC=local
CN=NewUser0267
SamAccountName = NewUser0267
OU = OU=MowOu,DC=mow,DC=local
CN=NewUser0270
SamAccountName = NewUser0270
OU = OU=MowOtherOU,DC=mow,DC=local

# update the CSV file 

PoSH>$newusers | select *,@{e={if ($_.name -eq 'NewUser0270'){"OU=MowOtherOU,DC=mow,DC=local"else {""}};name='OU'} | e
xport-csv -not c:\powershell\modUsers.csv
PoSH>import-csv c:\powershell\modUsers.csv | ft name,ou

Name                                                        OU
----                                                        --
NewUser0003
NewUser0009
NewUser0011
NewUser0012
NewUser0267
NewUser0270                                                 OU=MowOtherOU,DC=mow,DC=local


Note that you can just edit the CSV file but I did use select again like in the export examples in part 5 of the AD series,to show that you don't need to use the object and can nest any kind of script in in.

Now we have all the properties to start lets change the script to not only echo the properties but actualy do something.

#
# the first version that is actualy working :
 
filter new-AdUser ([System.DirectoryServices.DirectoryEntry]$importOU){

  # check for name field :

  if ($_.Name) {$CN= $_.name} Else {throw "Name is Mandatory"}

  # Use default OU or connect to OU given in CSV file 

  if ($_.OU) {
      $OU = new-object System.DirectoryServices.DirectoryEntry("LDAP://$($_.OU)")
  } 
  Else {
      $OU = $ImportOU
  }

  # create the new user :

  $NewUser = $ou.get_Children().add("CN=$($_.name)",'user')
  $NewUser.commitChanges()

  # If accountname is not given make it same as CN

  if ($_.Accountname) {$newUser.sAMAccountName = $_.Accountname} Else {$newUser.sAMAccountName = $_.name}
  $NewUser.commitChanges()

}

Now let's create the users in the CSV file, where I will overrule the OU for one account.

# make other OU to test

PoSH>($root.get_Children().Add("OU=MowOtherOU","organizationalUnit")).commitChanges()

# one account on other OU 

PoSH>import-csv c:\powershell\modUsers.csv | new-AdUser  $mowou

distinguishedName
-----------------
{OU=MowOu,DC=mow,DC=local}
SamAccountName = NewUser0003
{OU=MowOu,DC=mow,DC=local}
SamAccountName = NewUser0009
{OU=MowOu,DC=mow,DC=local}
SamAccountName = NewUser0011
{OU=MowOu,DC=mow,DC=local}
SamAccountName = NewUser0012
{OU=MowOu,DC=mow,DC=local}
SamAccountName = NewUser0267
{OU=MowOtherOU,DC=mow,DC=local}
SamAccountName = NewUser0270

# check if the users are there :

PoSH>$mowou.get_Children() |? {$_.name -like "NewUser*"} | ft cn,distinguishedName,sAMAccountName

cn                                      distinguishedName                       sAMAccountName
--                                      -----------------                       --------------
{NewUser0003}                           {CN=NewUser0003,OU=MowOu,DC=mow,DC=l... {NewUser0003}
{NewUser0009}                           {CN=NewUser0009,OU=MowOu,DC=mow,DC=l... {NewUser0009}
{NewUser0011}                           {CN=NewUser0011,OU=MowOu,DC=mow,DC=l... {NewUser0011}
{NewUser0012}                           {CN=NewUser0012,OU=MowOu,DC=mow,DC=l... {NewUser0012}
{NewUser0267}                           {CN=NewUser0267,OU=MowOu,DC=mow,DC=l... {NewUser0267}
{NewUser0270}                           {CN=NewUser0270,OU=MowOu,DC=mow,DC=l... {NewUser0270}

# Clean up created users for next test

PoSH>$mowou.get_Children() |? {$_.name -like "NewUser*"} |% {$mowou.get_Children().Remove($_)}
PoSH>$mowou.get_Children() |? {$_.name -like "NewUser*"} | ft cn,distinguishedName,sAMAccountName
PoSH>


Thats it for now, in the next post we will add some more properties and enable them etc. as in the third part of this series.also we will add some more checking and errorhandling etc, make it into a function on the way, and will add some more functionality as creating the Homedirectory etc. as the MMC also does.

Enjoy,

Greetings /\/\o\/\/
Tags :


Comments:
Anonymous Anonymous
Hi,

I have a powershell question. I store a password as below:

#read password
$password=read-host -AsSecureString "Password "

the print it as:

write-output "Password: $password"


How do I decrypt the password to use in my script?

Do I use "ConvertFrom-SecureString" to decrypt it. If so what key do I have to use?
 
Blogger /\/\o\/\/
you can use a .net method

MowPS>[System.Runtime.InteropServices.marshal]::SecureStringToBSTR($Password)
1245492
MowPS>[System.Runtime.InteropServices.marshal]::PtrToStringAuto(1245492)
Secret

or You can use the getnetworkcredential() method if you make it a credential object first :

MowPS>$cred = new-object System.Management.Automation.PSCredential user, $Password
MowPS>$cred.GetNetworkCredential().Password
Secret

for more info :

http://mow001.blogspot.com/2005/11/get-credential-and-decrypting.html

Saving password to a file:

http://mow001.blogspot.com/2005/11/more-on-cryptograpy-and-msh.html

Greetings /\/\o\/\/
 
Anonymous Anonymous
Thanks MoW. That worked. Thanks much!
 
Post a Comment



<< Home

Archives

October 2005   November 2005   December 2005   January 2006   February 2006   March 2006   April 2006   May 2006   June 2006   July 2006   August 2006   September 2006   October 2006   November 2006   December 2006  

$Links = ("PowerShell RC1 Docs"," PowerShell RC1 X86"," PowerShell RC1 X64"," Monad GettingStarted guide"," Monad Progamming Guide"," Monad SDK"," Monad videos on Channel 9"," MSH Community Workspace"," scripts.readify.net "," MonadSource"," www.reskit.net"," PowerShell Blog"," Under The Stairs"," computerperformance powershell Home"," proudlyserving"," MSH on wikipedia"," MSHWiki Channel 9"," Keith Hill's Blog"," Precision Computing"," PowerShell for fun"," MSH Memo (Japanese)"," monadblog")

find-blog -about "PowerShell","Monad" | out-Technorati.
find-blog -contains "","" | out-Technorati.
Google
 
Web mow001.blogspot.com

This page is powered by Blogger. Isn't yours?