Search code examples
windowspowershelllocalserver-administration

Simple Powershell questions (Creating a local ID and adding local administrator group plus some checks)


Slightly new to powershell and looking for some guidance. I'm trying to create a simple script to accomplish the following:

  1. Check if a local ID already exists on a list of servers
  2. If not, create one and add to local administrator group across the list of servers
  3. Log out results
$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.


Solution

  • 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"
        }
    }