Windows 10 Local User Creation via PowerShell - How to make it interactive? - powershell

I'm not sure if my problem has been described and resolved in another post, but I haven't found it...
I'm trying to create a PowerShell script to get a Local User Account created on Windows 10 machines that are not in AD nor domain. I want to have the possibility to enter the "first" and "last" names of the new user or at least the "username" and not need to modify this in the PS script file every time before running it.
I tried this code but it doesn't create any new users...
$FirstName = Read-Host -Prompt 'Enter User First Name:'
$LastName = Read-Host -Prompt 'Enter User Last Name:'
$Username=$FirstName.substring(0,1)+$LastName
New-LocalUser $Username -Description "INT-G-MAT Local User" -NoPassword

You could use
New-LocalUser -FullName "Fullname" -AccountNeverExpires $True -Description "Something"
By using ScriptBlock, you can create useraccounts on remote machines.
For example
Invoke-Command -ComputerName $Computername -ScriptBlock { # Start ScriptBlock
New-LocalUser -FullName "Fullname" -AccountNeverExpires $True -Description "Something"
} # End Scriptblock
If you want to check what accounts are on the remote machine,
Get-WmiObject -Class Win32_UserProfile
I would start something like this and then test until I think is acceptable in this script
Invoke-Command -ComputerName "Computername" -ScriptBlock { # Start ScriptBlock
$Fullname = Read-Host -Prompt "Enter User First Name:"
New-LocalUser -FullName $Fullname -AccountNeverExpires $True -Description "Something" -PasswordNeverExpires $True
} # End Scriptblock

Related

Power Shell issue with create user

what is here wrong with create a local user?
$user New-LocalUser -Name "test" -NoPassword -AccountNeverExpires -UserMayNotChangePassword -FullName "Test Admin" -Description "Test User Admin " | Set-LocalUser -PasswordNeverExpires $true
Because you pipe the returned object of New-LocalUser directly through to Set-LocalUser, the capturing variable $user will be $null.
As you can see in the docs, the Set-LocalUser cmdlet returns no output
The fix is easy: seperate these two commands in two separate lines.
Also, I would recommend using Splatting on cmdlets that take a lot of parameters to help keep the code readable as opposed to using extremely long code lines.
# create a Hashtable with all parameters and their values
# for use with the New-LocalUser cmdlet
$userParams = #{
Name = "test"
FullName = "Test Admin"
Description = "Test User Admin"
AccountNeverExpires = $true
NoPassword = $true
UserMayNotChangePassword = $true
}
# create the user and afterwards set another property to the user object
$user = New-LocalUser #userParams
$user | Set-LocalUser -PasswordNeverExpires $true
Add-LocalGroupMember -Group "Administrators" -Member $user
Add-LocalGroupMember -Group "Remote Desktop Users" -Member $user
Setting -PasswordNeverExpires $true shouldn't be necessary anyway, because you created the user with option -NoPassWord AND UserMayNotChangePassword
It is not working because of set-Localuser is added in user creation itself.
$user = New-LocalUser -Name "test" -NoPassword -AccountNeverExpires -UserMayNotChangePassword -FullName "Test Admin" -Description "Test User Admin "
$user | Set-LocalUser -PasswordNeverExpires $true
Add-LocalGroupMember -Group "Administrators" -Member $user
Add-LocalGroupMember -Group "Remote Desktop Users" -Member $user

New-LocalUser returns null but user account is created

I am creating a local user by running below command.
$LocalAccount = New-LocalUser "myaccount" -Password "*****" -FullName "My Account" -Description "My Account" -AccountNeverExpires -PasswordNeverExpires
According to Microsoft documentation, New-LocalUser command is supposed to return a LocalUser object.
Right after that, I am adding that account to Administrators group but it fails as $LocalAccount is null even though I can see that the account is created.
if ((Get-LocalGroupMember -Group "Administrators" -Member $LocalAccount).Count -eq 0)
{
Add-LocalGroupMember -Group "Administrators" -Member $LocalAccount
}
This happens only when I run this as part of a script. If I just run $LocalAccount = New-LocalUser "myaccount" -Password "*****" -FullName "My Account" -Description "My Account" -AccountNeverExpires -PasswordNeverExpires, it works fine and I can see $LocalAccount has new user info.
What am I missing here?
I think the problem is Get-LocalGroupMember which doesn't give you any output when run within the script. This means your If statement will always return false and the Add-LocalGroupMember is not getting executed.
Alternatively, you can add the user to the group at the time of account creation:
$LocalAccount = New-LocalUser "myaccount" -Password $Secure_String_Pwd -FullName "My Account" -Description "My Account" -AccountNeverExpires -PasswordNeverExpires -Verbose | Add-LocalGroupMember -Group "Administrators" -Verbose
if you want to keep your original script they try using write-output:
$LocalAccount = New-LocalUser "myaccount" -Password $Secure_String_Pwd -FullName "My Account" -Description "My Account" -AccountNeverExpires -PasswordNeverExpires -Verbose
if ((Get-LocalGroupMember -Group "Administrators" -Member $LocalAccount -Verbose -ErrorAction SilentlyContinue| Write-Output).Count -eq 0)
{
Add-LocalGroupMember -Group "Administrators" -Member $LocalAccount -Verbose
}
Your if statement is not helping because the account is freshly created using New-LocalUser so no need to check if it is part of the Administrators group.
Firstly, you must pass an encrypted password to New-LocalUser, so that is probably why you are not getting a return object. Also you need to use the .Name portion of the object when you perform the Add-LocalGroupMember or Get-LocalGroupMember. Also instead of '-eq 0' (which works), it's always better to use '-lt 1'. Lastly consider using 'measure' if you are trying to get a count.
Rough working example:
$passwd = ("thepassword" | ConvertTo-SecureString -AsPlainText -Force)
$AddObj = (New-LocalUser "myaccount" -Password $passwd -FullName "My Account" -Description "My Account" -AccountNeverExpires -PasswordNeverExpires)
if ((Get-LocalGroupMember -Group "Administrators" | where-object Name -match "\\${AddObj.Name}$" | measure).Count -lt 1)
{
Add-LocalGroupMember -Group "Administrators" -Member $AddObj.Name
}
Note this is just a rough example, you need to check for the user first and also it's better to use a variable for the account id and not the object IMO.

Nested Powershell Function

I am new to Powershell and I want to try and automate server decommission procedures because the current task is too manual. So I have two functions. Function 1 stores the domain admins credentials and function 2 executes the decom procedures.
Function decom{
Set-Variable domain,password -Scope Global
function user {
$user =Read-Host -Prompt "Enter user name"
$domain = "domain\"+$user
$password = Read-Host -Prompt "Enter domain password" -AsSecureString | ConvertFrom-String | Set-Content C:\test\password.txt
}
user
$remove_AD = Uninstall-ADDSDomainController -RemoveDnsDelegation -NoRebootOnCompletion New-Object System.Management.Automation.PSCredential $domain, $password -WhatIf
$remove_Domain = Remove-Computer -UnjoinDomainCredential New-Object System.Management.Automation.PSCredential $domain, $password -WhatIf
$remove_NetAdapter = Disable-NetAdapter -Name * -WhatIf
}decom

Powershell Get-Acl for folders without access permissions

I wrote a script, which gives me all the permissions of a folder + subfolders for a user/group. However, the script only works, if my user has at least read permissions on all these folders. If he has no permissions, get-acl is denied.
Is there any way to work around this, as I don't want to manually switch my user everytime I execute this script.
Can I execute a powershell script with a different user? And if yes, how?
Thank you in advance, Colin
You have a few options that I can think of:
Option 1:
Create a helper file with the actual code you want to run and call it script.ps1 for instance:
[array]$users = "user1","user2","user3"
foreach($user in $users){
$creds = Get-Credential -UserName $user -Message "Enter the Users Password"
$Session = New-PSSession -Credential $creds
Invoke-Command -Session $Session -FilePath C:\Path\to\some\script.ps1
}
Option 2: Run a job for each user. After every task is finished, the new user credentials will be asked. Just add the code to the scriptblock
[array]$users = "user1","user2","user3"
foreach($user in $users){
$creds = Get-Credential -UserName $user -Message "Enter the Users Password"
$target = $user
$job = Start-Job -scriptblock {
param ($username)
Get-Acl C:\Users\$user #Bla bla the rest of your script
} -Args $user -credential $creds
do{
#Wait for the job to finish
}until($job.State -ne "Running")
Write-Host "Job finished with state $($job.State)"
}
Hope this helps!
Note that the creds object can also be automated, if you don't wish to type all the time. (Security principles not taken into account ;) )
$users = #()
$users += #{
username = "User1"
password = "Pass123!"
}
$users += #{
username = "User2"
password = "Pass123!"
}
foreach($user in $users){
$creds = New-Object System.Management.Automation.PSCredential($user.username,($user.password | ConvertTo-SecureString -AsPlainText -Force))
#Add the rest of the script from the chosen option
}

AD Delegated user password change

I'm trying to write a code in PowerShell that will loop till the user would like to exit. Thus, allowing the delegated user to change passwords for student accounts.
I have tested the code for the password change and it works without any issues.
As soon as I try adding a while loop the code wont run.
#Open powershell as Administrator
Start-process Powershell -verb RunAs
# Connect to the Domain Controller
$session = New-PSSession -ComputerName "" -Credential (Get-Credential)
Invoke-Command $session -Scriptblock { Import-Module ActiveDirectory }
Import-PSSession -session $session -Module ActiveDirectory
#verify that you're connectedto the Domain
Get-ADDomainController -Filter * | Select-Object name
#run Password Change
$userid = Read-Host -Prompt 'Please enter the studnets login ID'
$newPassword = Read-Host -Prompt 'Please enter the studnets new password'
$run = 'yes'
while ($run -eq 'yes')
{
if (Get-ADUser -Filter {SamAccountName -eq $userid})
{
Set-ADAccountPassword $userid -Reset -NewPassword (ConvertTo-SecureString -Force -AsPlainText '$newPassword')
Write - Host "$userid` password has now been changed to: $newPassword"
}
else
{
Write - Host "$userid` does not exist, please try again."
}
$answer = Read-Host -Prompt 'Would you like to change another studnets password? [y|n]'
while ($answer -notcontains 'n' -or $answer -notcontains 'N' -or $answer -notcontains 'y' -or $answer -notcontains 'Y')
{
$answer = Read-Host -Prompt 'Please answer [y|n]'
}
if ($answer -eq 'y' -or $answer -eq 'Y')
{
$run = 'yes'
}
if ($answer-eq 'n' -or $answer -eq 'N')
{
exit
}
}
PowerShell is not case sensitive by default / design. So, no need to check for that.
Based on what you are after, you have potentially over engineered this item.
I'd suggest changing this to a simple to a Do..Until.
Clear-Host
do
{
"`n"
$TargetUser = Read-Host -Prompt 'Enter a user SamAccountName'
"Processing user $TargetUser"
Get-ADUser -Identity $TargetUser
"`n"
$answer = Read-Host -Prompt 'Would you like to see another user? [y|n]'
}
until ($answer -eq 'n')
"You entered $answer. Finished processing routine."
Enter a user SamAccountName: Administrator
Process user Administrator
...
Enabled : True
GivenName :
Name : Administrator
...
SamAccountName : Administrator
...
Would you like to see another user? [y|n]: y
Enter a user SamAccountName: sqladmin
Process user sqladmin
...
Enabled : True
GivenName : SqlAdmin
Name : SqlAdmin ServiceAccount
...
SamAccountName : sqladmin
...
Would you like to see another user? [y|n]: n
You entered n. Finished processing routine.
Personally, if it were me doing this, I'd approach this a different way.
Create file on a share that can be updated with user SamAccountName
/ ID's for target changes.
Read in that file in the code.
In the code, auto generate a password.
Do whatever additional steps as needed in the code.
Thus removing all the manual prompting labor.