Note
Access to this page requires authorization. You can try signing in or changing directories.
Access to this page requires authorization. You can try changing directories.
Question
Monday, July 14, 2014 8:25 PM
Hi,
I am trying to create user accounts via PowerShell instead of the Gui in server 2008 R2 (PowerShell 2.0).
I know how to create a user account with the following Power Shell command below is one from a dummy domain I created to practice.
"
PS C:\Users\Administrator> New-ADUser -SamAccountName "TestOut" -UserPrincipalNa
me "[email protected]" -GivenName "Test" -Surname "out" -DisplayName "Testou
t" -Name "Testout" -Enabled $true -Path "CN=users,DC=bwcat,DC=net,DC=int" -Accou
ntPassword (Read-Host -AsSecureString "Enter Account Password")
"
However when doing day to day tasks where I work normally we have a new hire, they contact IT and ask that a user account is created. I will ask who they would like to mirror.
I then would go into the gui pull up the user that they want to mirror right click him and choose copy. This would create a new user account that I would then fill out.
I am wondering if its possible to do this same thing via PowerShell, or if its not an option because it takes more work type up everything than it does to go into the gui and do it.
Anyway thanks for the help.
All replies (33)
Tuesday, July 15, 2014 7:05 PM ✅Answered | 2 votes
Hi Wilder, hi Mark,
first of all: The tutorial sources Mark posted - especially the book "Powershell 3 in A month of lunches" - are good to get a baseline start. A really great reference, especially when you try to learn it while still dealing with your daily business.
On another note, Wilder: While I fully agree that learning things sequentially is usually the best, I too jumped right in instead of learning how to walk first (though it's been some time now. Fewer years than you'd think, but still ...). So I thought I'd give you a little aid with that function husk, so you could just stuff interesting bits into an available structure, making use of the fun tools in a useful context (It's fun fiddling around with the commands, but if you have to type in all of them manually each time, using the GUI is often just faster. Doing fun things and being efficient with it feels even better though ...). So ... while I do agree with yourself, learn it the Correct & Proper Way, I also do intend to finish this little explanation about the husk, all the way to the end.
Everything below this paragraph is part of this.
function Copy-ADUser
{
<#
.SYNOPSIS
A brief description of the Copy-ADUser function.
.DESCRIPTION
A detailed description of the Copy-ADUser function.
.PARAMETER GivenName
A description of the GivenName parameter.
.PARAMETER Surname
A description of the Surname parameter.
.PARAMETER Template
A description of the Template parameter.
.EXAMPLE
PS C:\> Copy-ADUser -GivenName "Max" -Surname "Mustermann" -Template "Jonny.Normal"
.NOTES
Additional information about the function.
#>
[CmdletBinding()]
Param (
[Parameter(Mandatory = $true)]
[string]
$Surname,
[Parameter(Mandatory = $true)]
[string]
$GivenName,
[Parameter(Mandatory = $true)]
[string]
$Template
) # Create finished Strings
$JoinedName = $GivenName + "." + $Surname
# Create new User
$NewUser = New-ADUser -Surname $Surname -GivenName $GivenName -DisplayName "$Surname, $GivenName" -SamAccountName $JoinedName -Name "$Surename, $GivenName" -PassThru
# Copy from old User
$NewUser | Add-ADPrincipalGroupMembership -MemberOf (Get-ADPrincipalGroupMembership $Template | Where { $_.Name -ne 'Domain Users' })
# Do Whatever else you feel like doing
# ...
}
This is again the same function husk I posted earlier. Only this time, I filled a little logic (the pieces that were already posted in this thread). This time, I'll not only go over each part again ... I'll do it by reposting the segments and trying to show some examples on how to modify the parts. Thus some of it will be repetitive, but this way all the info is in one spot.
Segment: Comment Based Help
<#
.SYNOPSIS
A brief description of the Copy-ADUser function.
.DESCRIPTION
A detailed description of the Copy-ADUser function.
.PARAMETER GivenName
A description of the GivenName parameter.
.PARAMETER Surname
A description of the Surname parameter.
.PARAMETER Template
A description of the Template parameter.
.EXAMPLE
PS C:\> Copy-ADUser -GivenName "Max" -Surname "Mustermann" -Template "Jonny.Normal"
.NOTES
Additional information about the function.
#>
That's the premier documentation part of a function, that teaches a user what the function does and how to use it. It's what's shown when using the Get-Help cmdlet.
Comment texts are not restricted to single lines however. For example you could replace ...
.EXAMPLE
PS C:\> Copy-ADUser -GivenName "Max" -Surname "Mustermann" -Template "Jonny.Normal"
... with ...
.EXAMPLE
PS C:\> Copy-ADUser -GivenName "Max" -Surname "Mustermann" -Template "Jonny.Normal"
Creates a new user named Max Mustermann and copies the group memberships of the already existing user Jonny Normal to this new User
... and get an explanation on what the example does when using Get-Help with the -Detailed parameter (Explaining examples is always a good idea).
Segment: Parameter
[CmdletBinding()]
Param (
[Parameter(Mandatory = $true)]
[string]
$Surname,
[Parameter(Mandatory = $true)]
[string]
$GivenName,
[Parameter(Mandatory = $true)]
[string]
$Template
)
This is the segment that tells Powershell what input your function accepts. Each parameter of Copy-ADUser you set will be available in the next segment as a variable of the same name. You can add additional parameters if you need more information for your logic. For example, let's add a parameter that allows you to specify what Organization the new user should belong to:
[CmdletBinding()]
Param (
[Parameter(Mandatory = $true)]
[string]
$Surname,
[Parameter(Mandatory = $true)]
[string]
$GivenName,
[string]
$Organization,
[Parameter(Mandatory = $true)]
[string]
$Template
)
That's how that would look like. You may notice that I didn't add the line with "[Parameter(Mandatory = $true)] this time. This means you may add the Organization parameter when calling Copy-ADUser, but you need not.
Segment: Logic
# Create new User
$NewUser = New-ADUser -Surname $Surname -GivenName $GivenName -DisplayName "$Surname, $GivenName" -SamAccountName "$GivenName.$Surename" -Name "$Surename, $GivenName" -PassThru
# Copy from old User
$NewUser | Add-ADPrincipalGroupMembership -MemberOf (Get-ADPrincipalGroupMembership $Template | Where { $_.Name -ne 'Domain Users' })
# Do Whatever else you feel like doing
# ...
This is the part of the function that does the actual work. Compared to the first husk I posted, this time there are two commands in it (and some comments). First, I create a new user, using the information passed into the parameters -Surname and -GivenName. **Then I Copy the group memberships of the user identified by the information given by the -Template parameter.
So, let's modify it!
# Tell the user you are starting
Write-Host "Starting to create the user account for $GivenName $Surname"
# Create new User
$NewUser = New-ADUser -Surname $Surname -GivenName $GivenName -DisplayName "$Surname, $GivenName" -SamAccountName "$GivenName.$Surename" -Name "$Surename, $GivenName" -PassThru
# Tell the user you are copying Group Memberships
Write-Host "Copying the group-memberhips of $Template to $GivenName $Surname"
# Copy from old User
$NewUser | Add-ADPrincipalGroupMembership -MemberOf (Get-ADPrincipalGroupMembership $Template | Where { $_.Name -ne 'Domain Users' })
# Do Whatever else you feel like doing
# ...
Now after adding a few lines, the logic will tell us what it's doing (and do so before it is taking action)!
Hm ... didn't we create a change in the Parameter Segment to add an -Organization parameter? Let's use it!
# If the -Organization parameter was set, the $Organization variable will be longer than 0. Thus do ...
if ($Organization.Length -gt 0)
{
# Tell the user you are starting
Write-Host "Starting to create the user account for $GivenName $Surname in the Organization $Organization"
# Create new User
$NewUser = New-ADUser -Surname $Surname -GivenName $GivenName -DisplayName "$Surname, $GivenName" -SamAccountName "$GivenName.$Surename" -Name "$Surename, $GivenName" -Organization $Organization -PassThru
}
# If the -Organization parameter was NOT set, the $Organization variable will have a length of 0. Thus the if-condition does not apply, thus we do the else block
else
{
# Tell the user you are starting
Write-Host "Starting to create the user account for $GivenName $Surname"
# Create new User
$NewUser = New-ADUser -Surname $Surname -GivenName $GivenName -DisplayName "$Surname, $GivenName" -SamAccountName "$GivenName.$Surename" -Name "$Surename, $GivenName" -PassThru
}
# Tell the user you are copying Group Memberships
Write-Host "Copying the group-memberhips of $Template to $GivenName $Surname"
# Copy from old User
$NewUser | Add-ADPrincipalGroupMembership -MemberOf (Get-ADPrincipalGroupMembership $Template | Where { $_.Name -ne 'Domain Users' })
# Do Whatever else you feel like doing
# ...
There! Now we first check whether the **-Organization **parameter was set (it's not mandatory after all, so you can skip it). If it was set, do whatever is in the curly braces after if (...). However, if it wasn't set, do whatever is in the curly braces after else.
And that concludes my "minor" (and hopefully helpful) tutorial on how to use the function husk I posted :)
With this, whenever you find another cool command that helps you in the user creation process, you can simply add it, similar to what I did in these examples.
And if it all didn't make much sense, go through the tutorials in proper order and come back - it'll make much more sense then.
Cheers and good luck with PowerShell,
Fred
There's no place like 127.0.0.1
Monday, July 14, 2014 8:35 PM
Hi,
Take a look at the -Instance parameter of New-ADUser:
http://technet.microsoft.com/en-us/library/ee617253.aspx
Here's a good writeup you can reference:
http://dexterposh.blogspot.com/2013/02/create-new-ad-users-using-template.html
EDIT: My 2 cents - just use ADUC for this. That's probably going to be quicker in the long run. This is a great excuse to learn some new things (so you should do it at least once so you can learn), but I personally default to the GUI for this type of thing myself.
Don't retire TechNet! - (Don't give up yet - 12,950+ strong and growing)
Monday, July 14, 2014 8:41 PM
You could use
$olduser = get-aduser <existing user>
Then use properties of $olduser to fill in the blanks, but you'd still have to plug in all the unique values into the command, so it's probably not worth it unless you have a spreadsheet with those values and need to create more than a handful of users from an existing user. The path and group memberships are all the effort you're saving and you save that by right-click and copying anyway.
I hope this post has helped!
Monday, July 14, 2014 8:48 PM
Hi Mike,
Very Nice references. However, the last post of the second Dexter post states that when using the -instance that the group are not copied over.
So if that holds true that would defeat my purpose of using another account to copy using that command as our users have 10-15 groups and sometimes more associated with their accounts. Its one of the main reasons at my company that we use the gui copy command.
it may well be something that is not feasible to do via the PowerShell command line, but I just thought it would be really cool.
Good point Mike, it probably will take longer to do via command line than the GUI.
Monday, July 14, 2014 8:52 PM
Hi Mike,
Very Nice references. However, the last post of the second Dexter post states that when using the -instance that the group are not copied over.
So if that holds true that would defeat my purpose of using another account to copy using that command as our users have 10-15 groups and sometimes more associated with their accounts. Its one of the main reasons at my company that we use the gui copy command.
it may well be something that is not feasible to do via the PowerShell command line, but I just thought it would be really cool.
True, but it's pretty simple to copy group memberships too. You'd just need a second command:
Get-ADPrincipalGroupMembership tester1 | ForEach-Object {
If ($_.Name -ne 'Domain Users') {
Add-ADGroupMember $_.DistinguishedName -Members tester2
}
}
Don't retire TechNet! - (Don't give up yet - 12,950+ strong and growing)
Monday, July 14, 2014 8:56 PM
You could still use the get-aduser as I mentioned above with the .memberof property, but you'd have to massage the data in order to add the new user to each of the groups the existing user is a member of. It certainly isn't impossible to do, but in your example of onesy-twosy it just isn't worth it because you still need to supply all the unique values in the command.
If you had a list of a dozen users to model after one user and had to do it a couple times a week AND could easily get the information into a spreadsheet, that would be worthwhile. But if you have to populate the spreadsheet in order to use it for that purpose you're doing just as much data entry as manually copying in ADUC anyway.
I hope this post has helped!
Monday, July 14, 2014 8:57 PM
Fair enough.
So its sounding like the command line is not the more efficient use of time, in this particular matter, and the gui is in fact superior to PS here.
What about adding groups to a users account? is that something that is feasible in Power Shell?
Monday, July 14, 2014 9:01 PM
Hi Wilder,
it absolutely is possible. Actually, with a little skill you can build your own Copy-ADUser command!
After creating a new user (Let's call him "Max.Mustermann"), you can use this line to copy groupmembership:
Get-ADUser "Max.Mustermann" | Add-ADPrincipalGroupMembership -MemberOf (Get-ADPrincipalGroupMembership "Peter.Maier" | Where {$_.Name -ne 'Domain Users'})
For help on building your own commands without having to learn programming, see these two help texts:
Get-Help about_functions
Get-Help about_functions_advanced
Cheers,
Fred
There's no place like 127.0.0.1
Monday, July 14, 2014 9:11 PM
Hi Mike,
Very Nice references. However, the last post of the second Dexter post states that when using the -instance that the group are not copied over.
So if that holds true that would defeat my purpose of using another account to copy using that command as our users have 10-15 groups and sometimes more associated with their accounts. Its one of the main reasons at my company that we use the gui copy command.
it may well be something that is not feasible to do via the PowerShell command line, but I just thought it would be really cool.
True, but it's pretty simple to copy group memberships too. You'd just need a second command:
Get-ADPrincipalGroupMembership tester1 | ForEach-Object { If ($_.Name -ne 'Domain Users') { Add-ADGroupMember $_.DistinguishedName -Members tester2 } }
Don't retire TechNet! - (Don't give up yet - 12,950+ strong and growing)
Maybe I should look at just how to add a group to an AD account. That’s starting to look a bit complicated as there are so many things here above I am unfamiliar with.
Can we look at this line by line so I can start to understand it?
- Get-ADPrincipalGroupMembershiptester1 (is this going to get all the groups of the member tester1?)
- I then see the pipe and then “ForEach-Object” I am guessing this is a for if type statement as its in bracket like javascript or java would be. So what I read this saying is For each of the objects if they are this then do this.
- $_.Name –ne (got totally lost on what this command is)
- Add-ADGroupMember (this means add a group I guess)
- $_.DistinguishedName (little iffy on this)
- –Member (this is just saying for the domain object tester 2 you will do all that stuff it previously asked I am guessing)
Monday, July 14, 2014 9:18 PM
Part of the difficulty is I am trying to run before I can walk lol...
I can do some pretty neat things in powershell but its because of my google ability not because I can put together scripts or create my own yet. I am missing a lot of the basics.
I understand its a verb and then a noun normally and I know what the pipe is, and a few other things but at same time I am missing a lot of info to. Learning how to create an AD account got me all hyped up, and then I came to the forums because they used some extra parameters that I did not recognize and I am kind of chasing the rabbit around by his tail seeing neat things here and there but not having the practical, and much of the needed basic knowledge.
I have worked with Servers for a few years now but its been almost all gui based. Now I am working on getting my server 2008 MCSA and the 70-640 is touching on powershell so I am pulled once again in that direction.
so my apologies for being a bit ignorant on some of the things here and asking for it to be explained in a bit of detail.
Monday, July 14, 2014 9:18 PM
Hi Wilder,
another step-by-step :)
- Yes
- The foreach-object cmdlet does for each item you pipe into it (in this case each group) perform whatever is written within the curly braces (the "$_" variable within that block refers to the group being processed).
- -ne mean "not equal". The whole statement means that if the group being processed isn't named 'Domain Users' (the default group each new user is a member of and thus needs not be added. Please note that the group name is different depending on the AD language).
- This means add a user to the given group.
- The distinguished name of the group being processed (it's fairly unique)
- The "-Members" parameter of Add-ADGroupMember is the parameter where you specify the user to add to the group
Cheers,
Fred
There's no place like 127.0.0.1
Monday, July 14, 2014 9:26 PM
Another note:
There are two ways you can add users to groups (it's a matter of perspective):
You can add groupmemberships to a user (Add-ADPrincipalGroupMembership) ...
... or ...
you can add members to a group (Add-ADGroupMember).
Both yield the same effect, thus it can occasionally be confusing. Which you use is primarily dependent on whether you use it in a pipeline and what object is being passed in the pipeline. If you pass along a user object, it's Add-ADPrincipalGroupMembership (Get-ADUser "Max.Mustermann" | Add-ADGroupMembership "Domänen-Admins"), if you pass along a group, it's Add-ADGroupMember (Get-ADGroup "Domänen-Admins" | Add-ADGroupMember "Max.Mustermann").
Outside of a pipeline, use whichever you are more comfortable with. I can't say it ever made a difference for me.
Cheers,
Fred
There's no place like 127.0.0.1
Monday, July 14, 2014 9:40 PM
Finally, since I'm feeling like it, here's a little script husk, for you to fill out.
function Copy-ADUser
{
<#
.SYNOPSIS
A brief description of the Copy-ADUser function.
.DESCRIPTION
A detailed description of the Copy-ADUser function.
.PARAMETER GivenName
A description of the GivenName parameter.
.PARAMETER Surname
A description of the Surname parameter.
.PARAMETER Template
A description of the Template parameter.
.EXAMPLE
PS C:\> Copy-ADUser -GivenName 'Value1' -Surname 'Value2'
.NOTES
Additional information about the function.
#>
[CmdletBinding()]
Param (
[Parameter(Mandatory = $true)]
[string]
$Surname,
[Parameter(Mandatory = $true)]
[string]
$GivenName,
[Parameter(Mandatory = $true)]
[string]
$Template
)
# Create new User
# ...
# Copy from old User
# ...
# Do Whatever else you feel like doing
}
Copy that text into a script file (a *.ps1 file. Create a new txt file and rename the extension if you must, though I recommend using a Script editor like the free PowerGUI or the non-free but far superior Powershell Studio from Sapien. I recommend going for Powershell Studio if you think powershell is here to stay for you, it comes with a 45 day trial - just enough to get you addicted). Then add your own commands to it.
There are virtually no limits to what you can add there. Add a Mailbox in Exchange? No Problem. Create shares? Easy. Force the admin to finish a game of Tetris with score 20000+ before getting to copy the user account? Sure thing (that last one will take a bit to code though).
When you're done writing that script, import it like you would import a module, only use the file path instead of a module name (Import-Module "C:\temp\Copy-ADUser.ps1" for example). Then you can use the Copy-ADUser command like any other command out there.
Cheers,
Fred
There's no place like 127.0.0.1
Monday, July 14, 2014 10:29 PM
Thanks!
I will be replying soon.
I just got off work and have to drive home not to mention, I got tired of having to use web email to send emails from my virtual box guest os to my pc; as I could not copy and paste directly, so I installed guest additions and setup copy and paste. I will now be able to copy and paste directly from power shell to the forums.
I am going to test out, and try to add a couple of groups to my testout user account. I will post these CST before it gets to late.
I will also check out that powershell studio stuff. Power Shell is definitely here to stay for me I have been yearning to get into it for the last few years after I learned about it and each year the desire grows more and more. To me its like getting to turn 21 and hang out with the real adults (not that I am that young anymore but I am a toddler when it comes to PowerShell lol).
Anyway will post in a bit after I can digest this stuff and get settled and back home.
Tuesday, July 15, 2014 12:47 AM
Another note:
There are two ways you can add users to groups (it's a matter of perspective):
You can add groupmemberships to a user (Add-ADPrincipalGroupMembership) ...
... or ...
you can add members to a group (Add-ADGroupMember).
Both yield the same effect, thus it can occasionally be confusing. Which you use is primarily dependent on whether you use it in a pipeline and what object is being passed in the pipeline. If you pass along a user object, it's Add-ADPrincipalGroupMembership (Get-ADUser "Max.Mustermann" | Add-ADGroupMembership "Domänen-Admins"), if you pass along a group, it's Add-ADGroupMember (Get-ADGroup "Domänen-Admins" | Add-ADGroupMember "Max.Mustermann").
Outside of a pipeline, use whichever you are more comfortable with. I can't say it ever made a difference for me.
Cheers,
FredThere's no place like 127.0.0.1
Hi Fred,
Ok I got both of them to work, not sure about the other one you might have to provide an example for that one.
===Tested this one and it worked.======
Add-ADGroupMember RemoteVPN testout
============================ I used another parameter here called -Member==
Get-ADUser testout | Add-ADPrincipalGroupMembership -MemberOf TestGroup
=============================
I was curious about the quotation marks are they used the same in PS as they are the command line and netsh? Meaning if you have space or special character?
Tuesday, July 15, 2014 1:41 AM
Finally, since I'm feeling like it, here's a little script husk, for you to fill out.
function Copy-ADUser { <# .SYNOPSIS A brief description of the Copy-ADUser function. .DESCRIPTION A detailed description of the Copy-ADUser function. .PARAMETER GivenName A description of the GivenName parameter. .PARAMETER Surname A description of the Surname parameter. .PARAMETER Template A description of the Template parameter. .EXAMPLE PS C:\> Copy-ADUser -GivenName 'Value1' -Surname 'Value2' .NOTES Additional information about the function. #> [CmdletBinding()] Param ( [Parameter(Mandatory = $true)] [string] $Surname, [Parameter(Mandatory = $true)] [string] $GivenName, [Parameter(Mandatory = $true)] [string] $Template ) # Create new User # ... # Copy from old User # ... # Do Whatever else you feel like doing }
Copy that text into a script file (a *.ps1 file. Create a new txt file and rename the extension if you must, though I recommend using a Script editor like the free PowerGUI or the non-free but far superior Powershell Studio from Sapien. I recommend going for Powershell Studio if you think powershell is here to stay for you, it comes with a 45 day trial - just enough to get you addicted). Then add your own commands to it.
There are virtually no limits to what you can add there. Add a Mailbox in Exchange? No Problem. Create shares? Easy. Force the admin to finish a game of Tetris with score 20000+ before getting to copy the user account? Sure thing (that last one will take a bit to code though).
When you're done writing that script, import it like you would import a module, only use the file path instead of a module name (Import-Module "C:\temp\Copy-ADUser.ps1" for example). Then you can use the Copy-ADUser command like any other command out there.
Cheers,
FredThere's no place like 127.0.0.1
Hi Fred,
I got this all created and imported and changed my script security (everything I had to do I had to research so took a little bit lol, good stuff though)
== I put in the following===
PS C:\Users\Administrator> Set-ExecutionPolicy RemoteSigned
Execution Policy Change
The execution policy helps protect you from scripts that you do not trust.
Changing the execution policy might expose you to the security risks described
in the about_Execution_Policies help topic. Do you want to change the execution
policy?
[Y] Yes [N] No [S] Suspend [?] Help (default is "Y"): y
PS C:\Users\Administrator> Import-Module "c:\data\Copy-ADUser.ps1"
PS C:\Users\Administrator> Copy-ADUser Testout
cmdlet Copy-ADUser at command pipeline position 1
Supply values for the following parameters:
GivenName: BrianTest
Template: PSTest
PS C:\Users\Administrator>
=================================Not sure exactly what I am doing at this point====
Tuesday, July 15, 2014 4:59 AM
Hi Wilder,
Quotation**:**
Yes, quotations are used to make sure the console considers the whole thing a string, even if there are whitespaces in it. However, there are two different ways to do so which have some meaning. First off, just to make sure, a short introduction to variables in Powershell:
Anything that starts with a dollar symbol is a variable. You can use those to store information:
# First, create the variable $string
$string = "Hello World"
# Check out what's inside
$string
# Check out how placing it in regular quotes works out:
"So Fred said: $string"
# Check out how placing it in single quotes works out:
'So Fred said: $string'
as you can see, powershell interpreted what you input inside regular quotes, however, if you use single quotes it will stop doing so.
***About that script
***Well ... in the script you currently have three sections:
*Comment Based Help
*The CBH block is that first block (starts with "<#" and ends with "#>"). That's a comment block where you fill in some information on the function so you'll still know what it does in half a year without having to read all the details and try to make sense of it.
Try using Get-Help Copy-ADUser and Get-Help Copy-ADUser -Detailed after importing the script, to see what it does.
*Param
*The Param section starts with "[CmdletBinding()]" and ends with ")". Don't yet worry about what the details mean, suffice to say, this is where you define Input into the function, the information your script uses to do whatever it does in the next section.
Everything after
Everything after the Param section is where you type in what you want your function to do. For example, you could put in this line:
$NewUser = New-ADUser -Surname $Surname -GivenName $GivenName -DisplayName "$Surname, $GivenName" -SamAccountName "$GivenName.$Surename" -Name "$Surename, $GivenName" -PassThru
If you import the script afterwards and start the function, it will now create an ADUser (and additionally store that user into the variable $NewUser, so you can use it again later in the function, without having to reload it).
Btw, everything after a "#" in a line will be considered a comment by powershell and is being ignored. Comments can be very helpful in figuring out why you did something at a later time. It is not uncommon for one of my functions to have more comment than Script-Code.
Anyway, if you figure out which commands you need to use in creating a new user based on another user, you can just add them into the function and it will repeat them step by step. If you later notice you need some more input information, just expand the param section, adding another parameter.
Cheers,
Fred
There's no place like 127.0.0.1
Tuesday, July 15, 2014 4:12 PM
I don't want to disappoint you, and I want to understand but I am getting confused on the script. I am understanding most of the things you say such as comments and the $ for defining a variable.
I see you added this line:
$NewUser = New-ADUser -Surname $Surname -GivenName $GivenName -DisplayName"$Surname, $GivenName" -SamAccountName "$GivenName.$Surename" -Name "$Surename, $GivenName" -PassThru
I am not sure if your saying add that into the script some where after the word parameter, then save the script? I am confused though because there is stuff already there:
#>
[CmdletBinding()]
Param (
[Parameter(Mandatory = $true)]
[string]
$Surname,
Or maybe you meant type it at the command line?
I was able to pull up the help and an example, but when I did what the example said it didn't do anything even though it didn't give me any errors either
PS C:\Users\Administrator> Get-Help Copy-ADUser
NAME
Copy-ADUser
SYNOPSIS
A brief description of the Copy-ADUser function.
SYNTAX
Copy-ADUser [-Surname] <String> [-GivenName] <String> [-Template] <String>
[<CommonParameters>]
DESCRIPTION
A detailed description of the Copy-ADUser function.
RELATED LINKS
REMARKS
To see the examples, type: "get-help Copy-ADUser -examples".
For more information, type: "get-help Copy-ADUser -detailed".
For technical information, type: "get-help Copy-ADUser -full".
PS C:\Users\Administrator> Copy-ADUser -Surname John -GivenName wayne -Template
testout
PS C:\Users\Administrator>
PS C:\Users\Administrator> Get-Command -Template
CommandType Name Definition
Cmdlet Add-Content Add-Content [-Path] <String[...
PS C:\Users\Administrator> get-help Copy-ADUser -Examples
NAME
Copy-ADUser
SYNOPSIS
A brief description of the Copy-ADUser function.
EXAMPLE 1
PS C:\Copy-ADUser -GivenName 'Value1' -Surname 'Value2'
PS C:\Users\Administrator> Copy-ADUser -GivenName Bill -Surname Smith
cmdlet Copy-ADUser at command pipeline position 1
Supply values for the following parameters:
Template: testout
PS C:\Users\Administrator>
When I check to see if a user named bill was created with surname of smith and that it copied from -Template: Testout user who has like 5 groups nothing happened. I made sure to refresh.
===================================================== When I normally get confused I will reverse engineer something that works and analysis it, but since the script does not seem to do anything, and its a bit more complex I just seem to be getting a bit lost. At first I thought the script would copy a user taking the copied information like user groups and such and create a new user prompting for that new users input such as name and such, but I don't think that's what your saying here now. So I think I am off point on this one.
I am still reading this over and over I see you explain it here below and tell me where but my brain just is not digesting it very well. I will continue to try to discern this portion until maybe it sinks in.
*Param
*The Param section starts with "[CmdletBinding()]" and ends with ")". Don't yet worry about what the details mean, suffice to say, this is where you define Input into the function, the information your script uses to do whatever it does in the next section.
Everything after
Everything after the Param section is where you type in what you want your function to do. For example, you could put in this line:
Tuesday, July 15, 2014 4:23 PM
Ok thanks, that's clear and makes sense!
Ok I get the powerShell variable item and tested it out to see the difference, with double or single qoutes
PS C:\Users\Administrator> $string ="Hello World"
PS C:\Users\Administrator> $string
Hello World
PS C:\Users\Administrator> "So Fred said: $string"
So Fred said: Hello World
PS C:\Users\Administrator> 'So Fed said: $string'
So Fed said: $string
PS C:\Users\Administrator>
Thanks this makes sense as its very similar to programming language stuff that I took in past classes many years back.
I am also a firm believer in commenting, both code and tickets; though I normally have only did coding in an academic environment just to get through some class.
I detail my work order tickets though for the next tech!
=)
Tuesday, July 15, 2014 4:48 PM
Ok I am looking at this now more as code and a script than PowerShell and I think I was way off base on my thinking.
If I approach this as something like JavaScript or programming code then I can read what you created pretty easily.
I have written pieces of code for web pages in my java scripting that does something similar where it will go pull a block which is what happens there with your comments I think the "dot" "." and then the keyword sets that off. Its a bit different but similar enough.
Then under the actual function portion that code there is basically just assigning the users input to a variable.
However, this really does not do anything except call some stuff and store variables.
your then saying if I know the commands I can enter them between the following:
Param(
New-ADUser "Bill Smith"
)
Except there may be some other commands and items I don't know that needs to go in there, as I don't know the syntax for PowerShell.
For example you have Brackets, and the parameter word and then I thought $ meant define a variable yet you have it used with $true which would seem to be a condition not a variable. (a little confusing)
[Parameter(Mandatory =$true)]
[string]
$Surname
Tuesday, July 15, 2014 4:52 PM
He told you up front that his 'script' was a husk. Its a template of how a function should be laid out. He expected you to fill in the comment based help section and provide your own code after the last parameter line ) and before the closing }.
He also told you to look at Get-Help about_Function and Get-Help about_functions_advanced
Here is a link to the same information that could be found with that.
He even laid out in comments where he would put his commands in that function.
Replace the line ##...
Tuesday, July 15, 2014 5:10 PM
Put it in perspective.
Jog in place until your tired and gasping for breath. Then take a straw and try to breath through that straw and then see how easy it is to breath.
Or better yet put on an iron mask with tiny eye holes and then try to run away from someone without the helm.
That's how it can be looking a information where everything is new and unexplored.
When you start learning PowerShell they give you commands like Get-Services little one line commands easy and you think, ah PowerShell is wonderful and so basic.
Yet as you move through it you find out that its huge and so much out there that you don't recognize.
Yet when your in unfamiliar landscape and most everything is new (even though some parts may seem familiar) your perspective and ability to analysis can become skewed.
Fred has been awesome in helping and taking the time to explain things but that does not change the fact that its hard to see things clearly especially when most everything at first can seem alien and appears to be viewed through a pin hole.
One of the problems is that on some things I skipped the walking part and jumped into the running and backflip portion. It happens as that's what inspires interest and fascination, and there is nothing wrong with that as long as you keep it in perspective and remember to pull it back and eventually start in the beginning and start reviewing all the basic things.
I intend to start over at the beginning and explore the basic stuff, but I was already involved in this conversation, and was just trying to finish out this particular little adventure before moving forward.
Tuesday, July 15, 2014 5:21 PM | 1 vote
Yeah, I realized after a posted that my response come off as being mean. That was not my intent. But the greatest part of PowerShell is the awesome help that comes with it.
Get-Help is the most important cmdlet in PowerShell.
If you do want to go backwards, I really enjoyed the book PowerShell 3 in A month of lunches.
If video is more your bag, MVA has a video series that was done by Jeffrey Snover.
Getting Started with PowerShell 3.0 Jump Start.
Yes, PowerShell is large but the great thing about it is it is much easier to understand than some other languages.
Tuesday, July 15, 2014 6:44 PM
No problem, and thanks for the post.
I remember looking at PowerShell 3.0 a year ago and really liked it because there was commands for server side that really simplified things.
The only problem with 3.0 is that my current company uses 2.0, and server 2008 r2, and I am just a support server engineer and not someone in control of everything. In other words while I know that PowerShell 3.0 can be installed and used I am guessing that is probably not an option in regards to my company.
Of course, I could just learn 3.0 on my virtual servers.
However, my question is do you think its a good idea to skip version 2.0 as it seems to be the most widely used shell in the industry right now?
I guess that just depends on the perspective, but I was curious on the thoughts on that.
Tuesday, July 15, 2014 7:16 PM
Hi Wilder,
I'd say it makes sense learning Powershell 3 (or version 4, but the two handle very similar, so either is fine). Many things will still work in Powershell 2.0 and I think it makes more sense to learn the new stuff and figure out how the old version differed on an individual basis, when a command fails. Better than learning many deprecated practices that will soon have little effect on your production environment, once the upgrade hits.
Before the upgrade happens, just test things out on a v2 machine before releasing it into production.
Cheers,
Fred
There's no place like 127.0.0.1
Tuesday, July 15, 2014 7:24 PM
Hi Fred, excellent tutorial on functions. The one thing I tend to add to functions that are making new item or changing things is to allow for Common Parameters.
[CmdletBinding(SupportsShouldProcess=$true,
ConfirmImpact="Medium")]
Which makes it so with this function I could go
PS C:\Test> Copy-Aduser -GivenName 'Test' -Surname 'User' -Template 'username' -whatif
What if: Performing operation "New" on Target "CN=\, Test,CN=Users,DC=domain,DC=local".
What if: Adds all the specified member(s) to the specified group(s).
As well as allows for the use of the -Confirm parameter.
Tuesday, July 15, 2014 7:32 PM
Hi Mark,
thanks and I too like using that, but I try to avoid complexity (and things that can distract) when writing introductory texts.
Cheers,
Fred
There's no place like 127.0.0.1
Tuesday, July 15, 2014 8:47 PM
Awesome, and thanks for all the information. I really appreciate it I don't have anyone to mentor me and help, nor do I have any IT friends, and my IT co-workers don't want to talk about IT stuff unless they have to. To them its a job to me its something I love. I love learning period, be it physics, science, some random thing and of course IT.
So when I say its a real treat for someone who has advanced experience to take time out of their busy day to share time with me on something that is not only my job but my hobby I really mean it.
learning is one of the single most important things in my life, so this stuff is very important.
I feel bad when someone explains something and I don't get it and I have to ask again, because I don't want to annoy them, but as much as I feel bad the thirst for knowledge is stronger so I just have to cringe and ask again and take the smack down when it comes lol...
Fred you have did an awesome job explaining, and its very clear especially when you factor in we are doing this over a written forum. I appreciate that and give the utmost respect that you take the time in that endeavor.
I read over everything once and it seems pretty clear. I am going to study this probably reading over it 10-20 times over next 24 hours, and finally attempt to put it together and run it PowerShell as the last stage. I will certainly be back here to post after that but give me 12-48 hours so I can study all of this and then formulate my reply.
In the meantime I just wanted to say thanks!
Respectfully,
Brian
Tuesday, July 15, 2014 10:16 PM
Hi Brian,
glad to have been of assistance so far (and I've put this thread on my watched list, so take your time to mentally chew on this, I'll be there).
As it happens, I too turned my hobby into my job, so I enjoy writing about it. Furthermore, it's good practice trying to explain things in a forum to a complete stranger in text only. Some of my functions on the job are to teach Powershell to my fellow devs, and especially our techs (I work for an IT Service Provider, often building tools for the soldiers who go out there and fight against hardware failure, software failure and layer 8 failure). So, getting a little practice in never hurts. Especially when we'll be having the next apprentice in a couple of months (who in the long tradition of apprentices will start as a fairly empty piece of paper, ready to be imprinted, but little to build upon).
Soo ... I'm having fun, it's helping me improve and I get to help someone out. Doesn't get much more win, does it? :)
Cheers,
Fred
There's no place like 127.0.0.1
Tuesday, July 15, 2014 11:02 PM
Job very well done Fred, thanks for filling in all the blanks I left behind up there. =]
Don't retire TechNet! - (Don't give up yet - 12,950+ strong and growing)
Wednesday, July 16, 2014 1:00 AM
... layer 8 failure...
That's my new favorite stealth phrase :)
I hope this post has helped!
Thursday, July 24, 2014 3:20 PM
Hi Fred,
Sorry its been awhile. My school instructor at WGU wanted me to finish out my Comptia Project+ as its the last cert and class I have that is not server related. So I kind of got bushwacked on that and have put all resources into trying to soak up all that information. (I will say while the IT PM side has some interesting things its also very hard to read and you sometimes want to fall over in your chair, asleep).
Anyway I could not get that script to run. Did you try to run it and if so, and if its not to much problem could you paste the entire script here so I could try a copy and paste?
I will add any accounts to my test domain if needed. Anyway if your to busy that's fine as well but if you do have time I do appreciate it. Btw I hope that new person your training is coming along well and you are blessed in your endeavors!
Thanks,
Brian C.
Friday, July 25, 2014 7:08 AM
Hi Brian,
no need to apologize, been held up myself upon occasion :)
Generally, when something doesn't work, it usually helps to give the error message. I can't do all that much with a simple "It does not work". That said, I'm currently doing some test runs on my old lab system that still runs on Powershell 2 and there it did fail. Figured out what the culprit was as well, so here's a revision:
function Copy-ADUser
{
<#
.SYNOPSIS
A brief description of the Copy-ADUser function.
.DESCRIPTION
A detailed description of the Copy-ADUser function.
.PARAMETER GivenName
A description of the GivenName parameter.
.PARAMETER Surname
A description of the Surname parameter.
.PARAMETER Template
A description of the Template parameter.
.EXAMPLE
PS C:\> Copy-ADUser -GivenName "Max" -Surname "Mustermann" -Template "Jonny.Normal"
.NOTES
Additional information about the function.
#>
[CmdletBinding()]
Param (
[Parameter(Mandatory = $true)]
[string]
$Surname,
[Parameter(Mandatory = $true)]
[string]
$GivenName,
[Parameter(Mandatory = $true)]
[string]
$Template
)
# Create finished Strings
$JoinedName = $GivenName + "." + $Surname
# Create new User
$NewUser = New-ADUser -Surname $Surname -GivenName $GivenName -DisplayName "$Surname, $GivenName" -SamAccountName $JoinedName -Name "$Surname, $GivenName" -PassThru
# Copy from old User
$NewUser | Add-ADPrincipalGroupMembership -MemberOf (Get-ADPrincipalGroupMembership $Template | Where { $_.Name -ne 'Domain Users' })
# Do Whatever else you feel like doing
# ...
}
You will notice the new line where I build a "joinedName"? That stopped the cmdlet from complaining for me. It appears to have taken the strings rather literally (and "$" is not a legal symbol to use for a name. At least not for users) I'll edit my previous examples to match that too, in a moment.
Alas, the apprentice will only start in two months, I'll see then how blessed I am :)
Cheers,
Fred
There's no place like 127.0.0.1