AD Delegated user password change - powershell

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.

Related

Create a user on premise based on firstname and lastname

I am in a hybrid environment and I would like to create a user from exchange using a script.
Goals:
Create an account (Last name + first character of first name). If an account exists, add a number at the end. For example, King, John (Samaccountname should be KingJ1.. if exists, KingJ2...)
The UPN must be the first name.last name... If the last name already exists add a number to the last name. For example, King, John (UPN should be john.king1#contoso, if exists john.king2#contoso.com...)
If anyone can help me it would be really appreciated so that I can save some time. Thanks in advance
Connect-ExchangeOnline
$UserCredential = Get-Credential
$SessionEX2016 = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri .../PowerShell/ -Authentication Kerberos -Credential $UserCredential
Import-PSSession $SessionEX2016 -DisableNameChecking
$FirstName = Read-Host "Please enter the Firstname"
$LastName = Read-Host "Please enter the Lastname"
$NewUserLoginID = Read-Host "Please enter a new Login ID" #if the samaccountname exists add a digit
$Manager = Read-Host "Please enter the Login ID of the manager"
$Name = "$($LastName), $($FirstName)"
$DisplayName = $Name
$UPN = "$($FirstName).$($LastName)#contoso.com" #if the upn exists, add a digit to the last name
$PW = "Welcome$(Get-Random -minimum 0001 -maximum 9999)!"
$OU = "OU=Users,OU=Accounts,DC=com,DC=contoso" # it will creates the user in this OU by default and will move the user to OU where the manager is.
#Check to see if the user already exists in AD
if (Get-ADUser -F {SamAccountName -eq $NewUserLoginID})
{
#If user does exist, add a digit to samccountname and upn."
}
else
{
#Create User On-Premise
New-RemoteMailbox -Name $Name -FirstName $FirstName -LastName $LastName -SamAccountName $NewUserLoginID -OnPremisesOrganizationalUnit $OU -UserPrincipalName $UPN -Password (ConvertTo-SecureString -AsPlainText $PW -Force) -ResetPasswordOnNextLogon:$true -Archive
$ManagerOU = ((Get-ADUser -Identity $Manager).DistinguishedName -split '(?<!\\),', 2)[-1]
# next, get the user object of the user you want to move
$NewUser = Get-ADUser -Identity $NewUserLoginID
# now move NewUser to the OU where Manager is in
$NewUser | Move-ADObject -TargetPath $ManagerOU
}
You can add while loops to check if a name already exists or not and if so, append a sequence counter to it.
I would also use Splatting for the New-RemoteMailbox cmdlet to make the code more readable (no need for those very long lines of code)
Something like this:
Connect-ExchangeOnline
$UserCredential = Get-Credential
$SessionEX2016 = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri .../PowerShell/ -Authentication Kerberos -Credential $UserCredential
Import-PSSession $SessionEX2016 -DisableNameChecking
$OU = "OU=Users,OU=Accounts,DC=com,DC=contoso"
$PW = "Welcome$(Get-Random -minimum 0001 -maximum 9999)!"
$FirstName = Read-Host "Please enter the Firstname for the new user"
$LastName = Read-Host "Please enter the Lastname for the new user"
$AccountName = $LastName + $FirstName[0] # Last name + first character of first name
# test if a user with that accountname already exists and if so, append a sequence number
$count = 1
while (Get-ADUser -Filter "SamAccountName -eq '$AccountName'") {
$AccountName = '{0}{1}{2}' -f $LastName, $FirstName[0], $count++
}
$UPN = "$($FirstName).$($LastName)#contoso.com" #if the upn exists, add a digit to the last name
# test if a user with that UserPrincipalName already exists and if so, append a sequence number
$count = 1
while (Get-ADUser -Filter "UserPrincipalName -eq '$UPN'") {
$UPN = '{0}.{1}{2}#contoso.com' -f $FirstName, $LastName, $count++
}
# create a Hashtable for splatting parameters
$userParams = #{
Name = "$($LastName), $($FirstName)"
DisplayName = "$($LastName), $($FirstName)"
FirstName = $FirstName
LastName = $LastName
SamAccountName = $AccountName
OnPremisesOrganizationalUnit = $OU
UserPrincipalName = $UPN
Password = $PW | ConvertTo-SecureString -AsPlainText -Force
ResetPasswordOnNextLogon = $true
Archive = $true
}
# Create User On-Premise and move to the managers OU if possible
try {
New-RemoteMailbox #userParams -ErrorAction Stop
# now check if we can get a managers OU
$Manager = Read-Host "Please enter the Login ID of the manager"
$adManager = Get-ADUser -Filter "SamAccountName -eq '$Manager'"
if ($adManager) {
$ManagerOU = ($adManager.DistinguishedName -split '(?<!\\),', 2)[-1]
# next, get the user object of the new user and move it to the managers OU
Get-ADUser -Identity $AccountName | Move-ADObject -TargetPath $ManagerOU
}
else {
Write-Error "Could not find a manager with SamAccountName '$Manager'"
}
}
catch {
Write-Error $_.Exception.Message
}

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

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

How to combine first name and last name in powershell? [duplicate]

This question already has an answer here:
Powershell Active Directory DisplayName
(1 answer)
Closed 2 years ago.
Hello everyone I am currently learning PowerShell, and I have script were I can create a Active Directory User, And I am trying to combine the first name and last name (firstname.lastname) and set it where it says $logonname so the user will not have to input that information. Is there some type of command used to achieve that ?
import-module activedirectory
#Define variable
$OU ="OU=mine,DC=mine,DC=mine"
$firstname = Read-Host 'Enter New Users First Name'
$lastname = Read-Host 'Enter New Users Last Name'
$logonname = Read-Host 'Enter New Users Windows Logon Name'
$EmailAddress = "$logonname#mine.com"
$Description = Read-Host 'Job Title?'
$Landline = Read-Host 'Enter the Users Landline Phone (if applicable)'
$Mobile = Read-Host 'Mobile Phone? (If Applicable)'
$Password = Read-Host 'Please enter a secure password'
New-ADUser -Name "$firstname $lastname" -EmailAddress $EmailAddress -DisplayName "$firstname $lastname" -SamAccountName $logonname -Title $Description -UserPrincipalName "$logonname#mine.com" -GivenName $firstname -Surname $lastname -Description $Description -OfficePhone $Landline -MobilePhone $Mobile
Write-Host 'Setting Account Details...'
Write-Host 'Setting Password...'
Set-ADAccountPassword -Identity $logonname -NewPassword (ConvertTo-SecureString -AsPlainText "$Password" -Force)
Set-ADUser -Identity $logonname -PasswordNeverExpires $true
Write-Host 'Setting Home Directory to \\networklocation\Home'
Set-ADUser -Identity $logonname -HomeDirectory \\networklocation\home -HomeDrive H
Write-Host 'Enabling Account in Active Directory..
**NOTE**
The Account Will Take 30 Seconds To Enable, It Is Safe To Close The Script As Long as you See the "DONE" Prompt.'
Enable-ADAccount -Identity $logonname
Write-Host 'Done'
If you want to update your script so that $logonname is using the values from $firstname and $lastname then you can do that in a couple different ways.
I also see in the comments that you want a . in between.
This is how I would do it:
$logonname = "$firstname.$lastname";
As a side note, I personally don't have experience with AD, however, allowing the user to type in whatever they want, and then using that info could lead to problems.
What if the user types symbols that are not allowed in a username or in an email address?
If you are the only one using this script and you're just writing it to make your job easier, then that's probably fine. But I would be wary of allowing others to run it.
What happens if any one of these commands which depend on the previous command, fails?
I realize you said you're learning. So this is a good opportunity to learn about error handling, checking your inputs and verifying they are valid, etc.

Powershell Script outputs are merged instead of separated individually

I made this script to ping a computer name and if it's pingable, to return the username of the logged on user and if the user of the script so desires, a list of all the installed programs and a list of the installed printers the user is using.
When I run the script it returns the username and requires the users' input if they want to see the installed programs, the user answers Y or N. It asks the user afterwards if they want to the list of printers.
The script then gives an output of both the list of programs & printers as one answer.
My problem is that I would like the script to ask if the user wants the programs list, then to output the programs list, then prompt if the user wants the printers list, then output the printer list.
I have no idea how to go about this and have searched and experimented and have found no solution.
Any help or advice would be greatly appreciated :)
Apologies for the long post
# This script shows who is currently logged on to a machine
$PCNAME = Read-Host "Please enter computer name"
Write-Host "Pinging computer name..."
# If the computer responds to ping then the user name will be displayed
If (Test-Connection -ComputerName $PCNAME -Quiet)
{
$User = Get-WmiObject Win32_ComputerSystem -ComputerName $PCNAME | Select-Object -ExpandProperty UserName
$Time = Get-Date -DisplayHint Time
Write-Host ""
$CurUser = Write-Host "The current user logged in to $PCNAME is $User at $Time" -ForegroundColor Green
Write-Host ""
}
#PROGRAMS
$Programs = Read-Host "Would you like to see what programs $User has installed? Enter Y or N"
If ($Programs -eq "Y") {
Write-Host ""
Write-Host "Retrieving list of installed programs..."
Write-Host ""
Get-WmiObject -ComputerName $PCNAME -Class Win32_Product | sort-object Name | select Name
}
ElseIf ($Programs -ne "Y" -and $Programs -eq "N") {
Write-Host ""
Write-Host "Will not retrieve list of installed programs."
}
#PRINTERS
$Printers = Read-Host "Would you like to see the pinters that $User is using? Enter Y or N"
If ($Printers -eq "Y") {
Write-Host ""
Write-Host "Getting printers..."
Write-Host ""
# Collect port names and host addresses into hash table
$hostAddresses = #{}
Get-WmiObject Win32_TCPIPPrinterPort -ComputerName $PCNAME | ForEach-Object {
$hostAddresses.Add($_.Name, $_.HostAddress)
}
Get-WmiObject Win32_Printer -ComputerName $PCNAME | ForEach-Object {
New-Object PSObject -Property #{
"Name" = $_.Name
"DriverName" = $_.DriverName
"HostAddress" = $hostAddresses[$_.PortName]
}
}
}
ElseIf ($Printers -ne "Y" -and $Printers -eq "N") {
Write-Host ""
Write-Host "Could not get printers"
Write-Host ""
}
Else
{
Write-Host ""
Write-Host "Could not ping $PCNAME at $Time" -ForegroundColor DarkCyan
}
Write-Host ""
#$EndPrompt = ( Read-Host -Prompt "Press Enter to finish" )
There's better ways of doing this overall, but the simplest way to add this is:
#PROGRAMS
$Programs = Read-Host "Would you like to see what programs $User has installed? Enter Y or N"
If ($Programs -eq "Y") {
Write-Host ""
Write-Host "Retrieving list of installed programs..."
Write-Host ""
$Installed = Get-WmiObject -ComputerName $PCNAME -Class Win32_Product | sort-object Name | select Name
$Installed | Out-Host
}
ElseIf ($Programs -ne "Y" -and $Programs -eq "N") {
Write-Host ""
Write-Host "Will not retrieve list of installed programs."
}

Trying to add global security groups to a folder

I wrote a script to create a new folder based on some company variables and later on add a group with users to handle the permissions on this folder.
I can not find a decent way to add one, or more, AD groups to a folder in the same script.
Here is my script:
$parentfolder = Read-Host -Prompt "Please enter the name of the parent folder (i.e. FOLDER1234)"
$folder = Read-Host -Prompt "Please enter the name of the new network folder"
New-Item \\DC02\product\$parentfolder\$folder -type directory
Write-Host "Folder has been created!"
Start-Sleep -s 2
$newgroup = Read-Host -Prompt "Please enter the new group name for this folder (1234-1234-12xx format)"
$description = Read-Host -Prompt "Please enter the abbreviation of the product (i.e. PDPROD)"
NEW-ADGroup -Name $newgroup -GroupScope Global -Description $description -Path "OU=Project Groups,DC=ourdomain,DC=nl"
do {
$stringquit = Read-Host -Prompt "Please enter the member username's to add or press Q if you are done."
$userfilter3 = Get-ADUser -Filter {sAMAccountName -eq $stringquit}
if ($userfilter3 -eq $Null,"Q") {
Write-Host = "User does not exist in AD, please try again"
Start-Sleep -s 1
} else {
if ($stringquit -ne "Q") {
Write-Output -InputObject $stringquit | Out-File -Append c:\userlist.csv
} else {
Write-Host "You pressed Q, moving on."
}
}
} until ($stringquit -eq "Q")
$addgroup = "cn=$newgroup,ou=Project Groups,dc=ourdomain,dc=nl"
$list = Get-Content c:\userlist.csv
foreach ($user in $list) {
Add-ADGroupMember -Identity $addgroup -Member $user
}
#set permissions
$acl = Get-Acl \\DC02\product\$parentfolder\$folder
$ar = New-Object System.Security.AccessControl.FileSystemAccessRule("1234-all","Modify"."ContainerInherit,ObjectInherit","None","Allow")
$acl.SetAccessRule($ar)
Set-Acl \\DC02\product\$parentfolder\$folder $acl
Replace SetAccessRule() with AddAccessRule().