Manny-Tech Posted July 22, 2019 Posted July 22, 2019 I'd like to change all users UPNs within AD to [email protected] and then apply this said UPN as their proxyAddress. Does anyone have any sample scripts that I could modify?
Roberto Posted July 22, 2019 Posted July 22, 2019 I'd like to change all users UPNs within AD to [email protected] and then apply this said UPN as their proxyAddress. Does anyone have any sample scripts that I could modify? Why not do the heavy lifting for proxy address with an exchange email address policy?
FN-GM Posted July 23, 2019 Posted July 23, 2019 Why not do the heavy lifting for proxy address with an exchange email address policy? Many don't have exchange anymore. I am assuming the OP uses Office 365.
Roberto Posted July 23, 2019 Posted July 23, 2019 Many don't have exchange anymore. I am assuming the OP uses Office 365. I get the impression they have a hybrid config, and that’s only supported with an on premise exchange server, precisely for jobs like this.
Manny-Tech Posted July 23, 2019 Author Posted July 23, 2019 Many don't have exchange anymore. I am assuming the OP uses Office 365. Spot on. Probably should have specified that in my original post. It's a new tenancy we are migrating too. All UPNs are currently [email protected] I need to set them to their email address to make things simpler for logging into O365.
QwertyMash Posted July 28, 2019 Posted July 28, 2019 I can write you a Powershell script if you like to do this for all the accounts. Are they in a particular OU? Thank you.
bknaggs Posted July 28, 2019 Posted July 28, 2019 http://wisesoft.co.uk/software/bulkadusers/default.aspx is something I’ve used for this purpose.
QwertyMash Posted July 28, 2019 Posted July 28, 2019 (edited) Hello, Here is a quick script I just slapped together for you that would change all the users UPNs - to [email protected] - there is two variables at the top to change. It need ran as an administrator and on a device wither with RSAT installed or from a domain controller. I have done some very basic testing on my development domain and it worked but I recommend doing a few little tests of your own first. If you want any help or would like it to do more just fire me a message. Thank you, CaptainQwerty. # Script: UPN change # Author: CaptainQwerty # Date Created: 28/07/2019 #requires -module ActiveDirectory #requires -RunAsAdministrator # Change there two variables, the top one is your domain and the second one is the OU that contains the users $domain = "Example.co.uk" $ou = "OU=Staff,DC=Example,DC=co,DC=uk" write-host "Importing Acive Directory module" Import-Module ActiveDirectory # Getting all users from the OU $users = Get-ADUser -filter * -SearchBase $ou # For each user in the OU change their UPN foreach($user in $users){ # Generating the UPN $firstname = $user.GivenName $firstInitial = $firstname.substring(0,1) $upn = "$firstInitial.$($user.surname)@$domain" # Setting the users UPN set-aduser $user -UserPrincipalName $upn } edit: Fixed formatting Edited July 28, 2019 by QwertyMash 1
HPlum78 Posted July 28, 2019 Posted July 28, 2019 I would put a try catch on the set is my only thought on a quick pass on the script above. And some logging, by that i dont mean write-host... :-P
QwertyMash Posted July 28, 2019 Posted July 28, 2019 I would put a try catch on the set is my only thought on a quick pass on the script above. And some logging, by that i dont mean write-host... :-P Oh don't get me wrong I literally said I threw it together. I figured they could maybe add what they needed check wise and I totally agree with you haha For instance it doesn't check for other people already having that UPN, when you sat writing Powershell on the mobile website it gets a little tedious haha Original poster, if you'd like help finishing off the script to be more robust as suggested by the above just message me and while I'm at the PC I'd happily help. 1
HPlum78 Posted July 28, 2019 Posted July 28, 2019 Hay @QwertyMash I was not calling you there was just adding my suggestions based on your saying it had been thrown together. 1
QwertyMash Posted July 28, 2019 Posted July 28, 2019 Hay @QwertyMash I was not calling you there was just adding my suggestions based on your saying it had been thrown together. Spot on Yeah it needs more like haha it's just literally the core of what he asked for haha
HPlum78 Posted July 29, 2019 Posted July 29, 2019 (edited) Script: UPN change # Author: CaptainQwerty # Date Created: 28/07/2019 #Script updated by: Hplum78 #Date updated: 29/07/2019 #Added functions for Script logging and error handling, Script will now create a log file in the following location C:\PowerShell\Logs\ Folder #Depending on how this is run (in the ISE/ as a PS script) the log will take the form of or will be #Added -whatif to the SET-ADUser command (Remove this after you have tested the script) #requires -module ActiveDirectory #requires -RunAsAdministrator # Change the two variables, the top one is your domain and the second one is the OU that contains the users - removed the requirement for changing the domain var if this script is running on the domain that you are working in (HPlum78. <# .DESCRIPTION This function returns the filename with no extension of the current script .PARAMETER StackDepth the stackdepth the retrieve #> function Get-ScriptFilenameNoExtension { [CmdletBinding()] Param ( [Parameter(Position=0,Mandatory=$false)] [string]$StackDepth = 1 ) return [io.path]::GetFileNameWithoutExtension( $((Get-PSCallStack)[$StackDepth].ScriptName)) } <# .DESCRIPTION Setup global variable with full file path and filename of log file .PARAMETER None #> function Get-DefaultLogLocation { $LogRootPath = 'C:\PowerShell\Logs\' $scriptname = Get-ScriptFilenameNoExtension -stackdepth 3 return "$($LogRootPath)$scriptname\" + "$scriptname`_$(get-date -Format "yyyyMMdd_HHmmss").log" } <# .DESCRIPTION This function check to see if the object passed in is either null, empty or whitespace .PARAMETER o The object for the test to be carried out on #> Function Get-IsNotNullEmptyOrSpace { [CmdletBinding()] Param ( [Parameter(Position=0,Mandatory=$false)]$o ) $return = $false try { IF([string]::IsNullOrWhiteSpace($o)) { Write-verbose "Given object is NULL/empty/whitespace" } else { Write-verbose "Given object has a value" $return = $true } } catch { Write-verbose "Error: Given object is NULL/empty/whitespace" } return $return } <# .DESCRIPTION This function pads a string with chars .PARAMETER Str The string to be padded .PARAMETER PadChar The padding char .PARAMETER MaxLength The length of the string for the padding to add to .PARAMETER PadLeft If true, the padding will appear at the begining of the string otherwise by default it will appear at the end of the string #> function Set-PaddingToString { Param ( [Parameter(Position=0,Mandatory=$true)] [string]$Str, [Parameter(Position=1,Mandatory=$false)] [char]$PadChar = " ", [Parameter(Position=2,Mandatory=$false)] [int]$MaxLength = 7, [Parameter(Position=3,Mandatory=$false)] [bool]$PadLeft = $false ) try { if (!($PadLeft)) { $return = $Str.PadRight($MaxLength,$PadChar) } else { $return = $Str.PadLeft($MaxLength,$PadChar) } } catch { $return = $Str } return $return } <# .DESCRIPTION Enabled file based logging output from script .PARAMETER None #> function Set-FileLogging { $LogRootPath = 'C:\PowerShell\Logs\' if (Test-Path $LogRootPath){ $logfullpath = split-path (Get-DefaultLogLocation) Log-WriteDebug "Log root path exists need to check subfolder: $logfullpath exists" if (!(Test-Path ($logfullpath))) { Write-LogDebug "Need to create logging folder: $logfullpath" mkdir $logfullpath } $global:logfile = Get-DefaultLogLocation Log-WriteDebug "Setup global variable for logging path toer: $logfile exists" } else { Log-WriteWarn "Default root log folder does not exist" } } <# .DESCRIPTION Breakdown and output attributes of the error .PARAMETER ErrorRecord Error object to resolve #> function Resolve-Error { [CmdletBinding()] param( $ErrorRecord = ($error[0]) ) Write-verbose "Error Occurred. formatting..." $spacer = "-"*80 Set-StrictMode -Off #$output = "`n`r" | out-string $output += "Error details:" | out-string $output += $errorRecord | Format-List * -Force | out-string $output += $spacer | out-string $output += "InvocationInfo :" | out-string $output += $errorRecord.InvocationInfo | Format-List * | out-string $output += $spacer | out-string $output += "TargetObject :" | out-string $output += $errorRecord.TargetObject | Format-List * | out-string $output += $spacer | out-string $output += "Exception :" | out-string $output += $exception = $errorRecord.Exception | out-string for ($i = 0; $exception; $i++, ($exception = $exception.InnerException)) { $output += "Inner Exception $i :" | out-string $output += $exception | Format-List * -Force | out-string } return $output } <# .DESCRIPTION This function outputs message to console and/or output file (if set) .PARAMETER Message The message to write in the log file .PARAMETER ForColour name of a Colour to be used for in the forColour attribute .PARAMETER LogType the log type "INFO" #> Function Log-Write { [CmdletBinding()] Param ( [Parameter(Position=0,Mandatory=$false)] [string]$Message, [Parameter(Position=1,Mandatory=$false)] [string]$ForColour = "", [Parameter(Position=2,Mandatory=$false)] [string]$LogType = "INFO" ) if (Get-IsNotNullEmptyOrSpace $logFile) { $timeStamp = (get-date).ToString() #get the date and time on the system now $logentry = (Set-PaddingToString $LogType) + " | " + $timeStamp + " | " + $Message $logentry | out-file -filepath $logFile -Append } if( $ForColour -eq "") { Write-Host "$LogType | $Message" } else { Write-Host "$LogType | $Message" -foregroundcolor $ForColour } } <# .DESCRIPTION Display and/or log to file of error message in appropriate Colour .PARAMETER Message message to be displayed/logged .PARAMETER ErrorRecord Describes a terminating or nonterminating error that occurred during the processing of a command #> function Log-WriteError { [CmdletBinding()] Param ( [Parameter(Position=0,Mandatory=$false)] [string]$Message, [Parameter(Position=1,Mandatory=$false)] [system.Management.Automation.ErrorRecord]$ErrorRecord=$null ) if ($Message -ne $null -and $ErrorRecord -eq $null) { Log-Write -forColour "red" -logtype "ERROR" -message $Message } if ($ErrorRecord -ne $null) { Log-WriteError -forColour "red" -logtype "ERROR" -message ("$Message | Error Details:`n`r$(Resolve-Error($ErrorRecord))" ) } } <# .DESCRIPTION Display and/or log to file a warning message in appropriate Colour .PARAMETER Message Message to be displayed/logged #> function Log-WriteWarn { [CmdletBinding()] Param ( [Parameter(Position=0,Mandatory=$true)] [string]$Message ) Log-Write -forColour "darkyellow" -logtype "WARN" -message "$Message" } <# .DESCRIPTION Display and/or log to file of info message in appropriate Colour .PARAMETER Message Message to be displayed/logged #> function Log-WriteInfo { [CmdletBinding()] Param ( [Parameter(Position=0,Mandatory=$true)][string]$Message ) Log-Write -message $Message -logtype "INFO" } <# .DESCRIPTION Display and/or log to file of debug message in appropriate Colour .PARAMETER Message debug message to be displayed/logged #> function Log-WriteDebug { [CmdletBinding()] Param ( [Parameter(Position=0,Mandatory=$true)] [string]$Message ) if ($debug -eq 1) { Log-Write -message $Message -logtype "DEBUG" } } Set-FileLogging $domain = $env:USERDNSDOMAIN Log-WriteInfo "Working Doamin is $($Domain)" #$ou = "OU=Staff,DC=Example,DC=co,DC=uk" Log-WriteInfo "Working OU is $($ou)" Log-WriteInfo "Importing ActiveDirectory" Try{ Import-Module ActiveDirectory Log-WriteInfo "ActiveDirectory Module imported sucessfuly" } Catch{ Log-WriteError "Failed to Import ActiveDirectory Module - Terminating Script" } # Getting all users from the OU Try{ Log-WriteInfo "Getting Users info from $($ou)" $users = Get-ADUser -filter * -SearchBase $ou } Catch{ Log-WriteError "Failed to get Users from $($ou)" } # For each user in the OU change their UPN foreach($user in $users){ Try{ # Generating the UPN Log-WriteInfo "Gernerating UPN for User $(($user).name)" $firstname = $user.GivenName $firstInitial = $firstname.substring(0,1) $upn = "$firstInitial.$($user.surname)@$domain" Log-WriteInfo "New UPN for $(($user).name) is $($upn)" # Setting the users UPN Log-WriteInfo "Setting UPN for User $(($user).name)" set-aduser $user -UserPrincipalName $upn -whatif #Remove -whatif to arm this script } Catch{ Log-WriteError "Failed to set UPN for $(($user).name)" } } The Error logging can been seen in the attached file. Feel free to grab the error handling functions from the above to use in your own scripts. Harry_20190729_085817.txt Edited July 29, 2019 by HPlum78 1
HPlum78 Posted July 29, 2019 Posted July 29, 2019 Just noticed that i have mangled the log file in my attempts to anonymise the data but its there to show the format of the logging rather than anything else. If anyone needs more info on what those functions do that i have added feel free to ask but they are essentially the framework to enable logging of what you are doing in a PS script one of the functions sets out the formatting with the pipes and the likes in the log file. Hope they help. H.
QwertyMash Posted July 29, 2019 Posted July 29, 2019 This is where he replies and says he has already sorted it haha
HPlum78 Posted July 29, 2019 Posted July 29, 2019 Yeah I bet.... Thought that someone would say that I had over done it! Question I am asking myself is have I? (do the functions make sense, or have I scared everyone off it because of all the code) What I do is have those functions in a separate module and then call them from my other scripts. What is not there is another few functions that I use for searching the log location on the script sever. As already noted the functions set out a framework for logging means that all my scripts log in the same format accross the board. 1
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now