Local user accounts creation on remote computers in a workgroup

0

I am trying to create a simple script that prompts a local admin user to create a local user account on 6 remote computers in a Windows Workgroup. The script should prompt for the name of the user, password, and the group to which it will be a member of, and repeats the execution of the commands in all 6 computers while the script initiated only once. All 6 computers have the admin account with the same username/password.

I know the PS commands that can be used are - New-LocalUser, Add-LocalGroupMember and PSSession, but I just can’t make it automated enough to run with the minimal input by a local admin. Thanks!

Fromusofa,
Welcome to the forum. :wave:t3:

What exactly is your question? :thinking:

And please keep in mind …

This forum is for scripting questions rather than script requests. We do not write customized and ready to use scripts or solutions on request.

We actually expect you to make an own attempt at the first place to get your task done or to solve your problem. If you have done so already please document here what exactly you have done and show your code. Then we probably might be able to help you step further.

BTW:
When you crosspost the same question at the same time to different forums you should at least post links to the other forums along with your question to avoid people willing to help you potentially wasting their time.

Thanks

1 Like

I tried the following script and saved it on PC01 to run from Powershell. However it gives an error that account already exists whenever it tries to create the account on PC02 and PC03 after it successfully creates the account on PC01. Also it does not Read host when remoting in to PCs.

Enter-PSSession -ComputerName PC01 New-localUser Add-LocalGroupMember -Group Users Exit-PSSession

Enter-PSSession -ComputerName PC02 New-localUser Add-LocalGroupMember -Group Users Exit-PSSession

Enter-PSSession -ComputerName PC03 New-localUser Add-LocalGroupMember -Group Users Exit-PSSession

Did you read my answer on the other thread? :thinking: Why did you pick this one to continue? :man_shrugging:t3:

As I already mentioned in thje other thread: You should use Invoke-Command instead of Enter-Pssession.

Obviously you do not open a remote PSSession to the computer you specified. Instead PowerShell runs the commands locally what fails because there already is a user with the specified name - you just created it. :man_shrugging:t3:

when I type the following script in Powershell, the command gets executed without any error, but it prompts for user name, password and again the name to add in the Users group for each PCs. how do I loop or array it so it only prompts for the username, password and the name of the group only once., thanks.

$PC="PC01","PC02","PC03"
Invoke-Command $PC -ScriptBlock {New-LocalUser;Add-LocalGroupMember -Group "Users"}

Since you don’t specify name, password of the user you want to create and the account you want to add to the group “Users”, PowerShell asks for each remote computer for it. :man_shrugging:t3:

If you want to create local accounts on all remote computers with the same name and password you should query it before you run the command on the remote computers.

The task you’re asking for is quite common and it has been asked for a lot of times and it has been answered a lot of times already. You don’t have to re-invent the wheel again and again. Just use your prefered internet search engine and look for
“PowerShell prompt for username and password” and you will find more than enough examples to get inspired by.

To use the locally filled variable in a remote command you may use scope modifier USING:. You can read more about that here:

Thanks @Olaf for pointing me to USING:. I got it working now, but still have one more thing to resolve. I would like to give FullControl access to the user that gets created to the folder created by the last line of the following script. Get-Acl and Set-Acl are so atrocious and there is no folder to copy the ACL from anyway. Can you please help? Thanks.

$PC="PC01","PC02","PC03"
$Username = Read-Host "Enter the Username"
$Password = Read-Host "Enter the Password" -AsSecureString
$Usergroup = Read-Host "Enter the Group Name" 
Invoke-Command $PC -ScriptBlock {New-LocalUser $Using:Username -Password ($Using:Password);Add-LocalGroupMember -Group $Using:Usergroup -Member $Using:Username}
New-Item -Path "\\PC01\Users\Public\Desktop\ATIP" -Name "$Username" -ItemType Directory

You don’t have to use Set-Acl. :point_up:t3: … icacls is still available on all Windows versions. Or you could even use third party tools like the old but still flawlessly working SetACL from Helge Klein.

If you want to try Set-Acl anyway you should take a look at the example #5. It’s not copying an existing ACL. It creates an ACL object and adds it to the existing ACL.

Thank you for clarifying about how Windows works with ACL assignment with Get-Acl and Set-Acl.
With the Example 5, I was able to create the subfolder named as user’s name, hoever it does not seem to have the permissions inherted to it from the parent folder and it has give the full control to the user for that folder only and not the subfolders and files. I tried few things with $acl.SetAccessRuleProtection($False,$true), but to no avail. how come. I will probably look in other options you mentioned if this one script does not work for this purpose at all.

Thanks.

I dug through my box of old things again and found a script I used to move homedirs from one server to another … you might find one or two lines of the code helpful for your project.

PowerShell data file with the config settings for the script (Extension *.psd1, and it has to have the same base name like the script!!!)

@{
    ADDomain     = 'contoso'
    SourceServer = 'sourceServer'
    SourceDrive  = 'E'
    SourceDir    = 'HomeDir'
    LogFolder    = '\\LogServer\logs\FileServer\sourceServer-targetServer\HomeDirMove'
    TargetServer = 'targetServer'
    TargetDrive  = 'E'
    TargetDir    = 'Home'
    USerList     = 'User1', 'User2', 'User6', 'User5329', 'User0'
}

Script:

#Requires -Modules ActiveDirectory

$Config = Import-PowerShellDataFile -Path $($MyInvocation.MyCommand.Definition).Replace('.ps1', '.psd1')

if ($env:COMPUTERNAME -ne $Config.TargetServer) {
    Set-Location -Path \
    Clear-Host
    "`n`n`n`n`n`n`t`t`t`t`t`tThis script is meant to run only on the server: ""$($Config.TargetServer)""!!!`n`n"
    Start-Sleep -Seconds 7

    exit
}


$TimeStamp = Get-Date
$LogFileName = 'Move_HomeShare_{0}.log' -f $TimeStamp.ToString('yyyyMMdd-HHmmss')
$LogFile = Join-Path -Path $Config.LogFolder -ChildPath $LogFileName

$Source = '\\{0}\{1}$\{2}' -f $Config.SourceServer, $Config.SourceDrive, $Config.SourceDir
$SourceFolderList = Get-ChildItem -Path $Source -Directory  | Where-Object -Property Name -in -Value $Config.USerList #| Select-Object -First 1

$HomeShareList = 
Get-SmbShare | 
    Where-Object -Property Path -Match -Value ([REGEX]::Escape('\HOME\'))

$HomeShareHash = 
$HomeShareList |
    Group-Object -AsHashTable -Property Name



foreach ($SourceFolder in $SourceFolderList) {
    $ADUser = Get-ADUser -Identity $SourceFolder.Name -Properties DisplayName -ErrorAction SilentlyContinue
    if ($ADUser.sAMAccountName -eq $SourceFolder.Name) {
        $HomeDirNew = '\\{0}\{1}$\{2}\{3}' -f $Config.TargetServer, $Config.TargetDrive, $Config.TargetDir, $SourceFolder.Name
        if (-not (Test-Path -Path $HomeDirNew)) {
            $TargetFolder = New-Item -Path $HomeDirNew -ItemType Directory

            $ACL = Get-Acl -Path $TargetFolder.FullName
            $Owner = New-Object System.Security.Principal.NTAccount('Builtin', 'Administrators')
            $ACL.SetOwner($Owner)
            $HomeDirUser = '{0}\{1}' -f $Config.ADDomain, $ADUser.sAMAccountName
            $AccessRule = New-Object System.Security.AccessControl.FileSystemAccessRule($HomeDirUser, 'modify', 'ContainerInherit, ObjectInherit', 'None', 'Allow')
            $ACL.SetAccessRule($AccessRule)
            Set-Acl -Path $TargetFolder.FullName -AclObject $ACL 
        }
        if ((-not $HomeShareHash) -or (-not ($HomeShareHash[$ADUser.sAMAccountName]))) {
            ## UNC source path -> local NTFS path
            $Drive = [System.IO.Path]::GetPathRoot($HomeDirNew)
            $Dumps = $HomeDirNew.Substring($Drive.Length)
            $Drive = $Drive.Substring($Drive.LastIndexOf('\') + 1).Replace('$',':')
            $NTFSPath = "$Drive$Dumps"


            $NewSmbShareSplat = @{
                Name        = $ADUser.sAMAccountName
                Path        = $NTFSPath
                Description = 'HomeDir {0}' -f $ADUser.DisplayName
                FullAccess  = 'everyone'
            }
            New-SmbShare @NewSmbShareSplat
        }
        $RobocopyLogFile = '{2}\robocopy_{0}_{1}.log' -f $TimeStamp.ToString('yyyyMMdd-HHmmss'), $ADUser.sAMAccountName, $Config.LogFolder
        $Destination = '{0}\' -f $HomeDirNew

        robocopy $SourceFolder.FullName $Destination /e /purge /nfl /ndl /ns /nc /np /r:0 /w:0 /LOG:$RobocopyLogFile /tee
    }
    else {
        "No AD User found for folder '$($SourceFolder.FullName)'" | Out-File -FilePath $LogFile
    }
}

Again: the script AND the PowerShell data file have to have the same base name for this to properly work.

1 Like

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.