Slightly new to powershell and looking for some guidance. I'm trying to create a simple script to accomplish the following:
$serverlist = Get-Content C:\temp\servers.txt
$credential = Get-Credential
foreach ($server in $serverlist){
#User to search for
$USERNAME = "John"
#Declare LocalUser Object
$ObjLocalUser = $null
Invoke-Command -Credential $credential -Authentication Default -ComputerName $Server -ScriptBlock {
$ObjLocalUser = Get-LocalUser "John"
#Create the user if it was not found (Example)
if (!$ObjLocalUser) {
Write-Verbose "Creating User $($USERNAME)" #(Example)
NET USER "John" "Generic Password" /ADD /passwordchg:no
NET LOCALGROUP "Administrators" "Joe Doe" /ADD
}
else {
Write-Verbose "John" already exists"
}
}
}
P.S, just using generic credentials for simplicity, will convert to best standards afterwards. Just trying to get more experience writing some Powershell and would probably convert to a custom function later on.
According to your script, I note the following points that could be enhanced
1- you don't have to use the for loop to iterate through the servers list, instead you can pass the server list array directly to the ComputerName
parameter of the Invoke-Command
get-help Invoke-Command
Invoke-Command [[-ComputerName] <string[]>]
# <string[]: indicate that the computername property accepts an array not string
so in your script you could use it as follow
Invoke-Command -Credential $credential -Authentication Default -ComputerName $Serverlist {...}
2- in the Invoke-Command
, you search if the user exist or not using the command
Get-LocalUser "John"
but this will give you an error if the user doesn't exist
PS C:\Windows\system32> Get-LocalUser john
Get-LocalUser : User john was not found.
At line:1 char:1
+ Get-LocalUser john
+ ~~~~~~~~~~~~~~~~~~
+ CategoryInfo : ObjectNotFound: (john:String) [Get-LocalUser], UserNotFoundException
+ FullyQualifiedErrorId : UserNotFound,Microsoft.PowerShell.Commands.GetLocalUserCommand
instead of that you could search for the user using:
Get-LocalUser | where {$_.name -eq $USERNAME})
3- you don't need to use the variable $ObjLocalUser
, you could check directly the search result using the if condition as follow:
if (!(Get-LocalUser | where {$_.name -eq $USERNAME})) {
Write-output "Creating User $USERNAME"
} else {
Write-output "User: $USERNAME already exists"
}
Finally: in order to use the a local variable inside the invoke-commnd
you could use the Using
scope modifier to identify a local variable in a remote command.
so the script could be something like that:
$serverlist = Get-Content C:\temp\servers.txt
$credential = Get-Credential
$USERNAME = "John"
Invoke-Command -Credential $credential -Authentication Default -ComputerName $serverlist -ScriptBlock {
#Create the user if it was not found (Example)
if (!(Get-LocalUser | where {$_.name -eq $Using:USERNAME})) {
Write-output "Creating User $Using:USERNAME"
NET USER $Using:USERNAME "Generic Password" /ADD /passwordchg:no
NET LOCALGROUP "Administrators" $Using:USERNAME /ADD
} else {
Write-output "User: $Using:USERNAME already exists"
}
}