UPN = Test/User@contoso.com

This topic contains 12 replies, has 6 voices, and was last updated by  Dan Potter 2 years, 4 months ago.

  • Author
  • #35666

    Recco Bucceri

    Hey all,

    So i am in the process of cleaning up active directory at a client and part of that clean up is amending UPNs that have invalid characters in them, such as ?/#$%^&*'

    I want to right a script that searches the whole forest. Now i know that i can do this using:

    Where-object {$_.UPN -like "/" -or "'"}

    And continue the or statement until i have included all the characters i want to search for. My question is there a neater way to perform the search instead of individually listing them between -or?

  • #35671

    Max Kozlov

    read about regex

    -match '[\?/#\$%^&*'']'

  • #35677

    Bob McCoy

    Actually your first example is incorrect. That's not how the -or operator works. And the syntax for the -like operand is incorrect. You would have to use ...

    Where-object {$_.UPN -like "*/*" -or $_.UPN -like "*'*"}

    RegEx would definitely be a better option.

  • #35678

    Bob McCoy

    Based on Max's pattern above, you could do something along these lines.

    # Sample data for the demo, good and bad samples.
    $upnList = @'
    '@ -split "`r`n"
    $pattern = [regex]'[\?/#\$\\%^&*'']'
    foreach ($upn in $upnList)
        # This script assumes you are replacing bad characters with an
        # underscore.  Or you could change the replacement to '' in order
        # to just delete the bad characters.
        $upn = $upn -replace $pattern,'_'
  • #35696

    random commandline

    This will replace non alpha-numeric characters from the loginname part of the UPN. You don't have to worry about selecting characters. This is fine for the English language. I used Bob's list with my example.

    # Separate UPN, remove non alpha-numeric characters
    # Display new UPN
    foreach ($upn in $upnList)
    {$m = $upn -match "(?'name'.*)(?'domain'@.*)"
        $newname = $Matches['name'] -replace '\W'
        $newupn = "{0}{1}" -f $newname,$Matches['domain']
  • #35706

    Aapeli Hietikko

    Hi all, this will be my first post on these forums so don't kill me 😉

    Mix and match from above and from my habits

    I'd take all users first to a variable, just to play with it faster and not to roll all the users again and again. Also based on my experience it's fast to play with it when it's in the memory.

    $pattern = [regex]'[\?\/\#\$\\\%\^\&\*'']'
    $ADUsers = get-aduser -fi * | select userprincipalname 
    $ADUsers | where {$_ -match $pattern}

    If you are searching something else from the UPN then I would split it from @ and look only in to the prefix part

  • #35732

    Recco Bucceri

    Thanks so much for all the responses!

    Here is my final script. I am always open to crits on ways to better fine tune or do it differently. Always looking to learn more!

    Can the same regex principle apply to objectclass? So for example would the following work:
    $ObjectClass = [regex]'[\group\user\contact]'

    Final script__________________________________________

    $Domains = $null
    $Domain = $null
    $DomainList = $null

    $pattern = [regex]'[\?\/\#\$\\\%\^\&\*"]'

    $objForest = [System.DirectoryServices.ActiveDirectory.Forest]::GetCurrentForest()
    $DomainList = @($objForest.Domains | Select-Object Name)
    $Domains = $DomainList | foreach {$_.Name}

    #This will search each email through all domains
    foreach($Domain in ($Domains))
    Get-ADObject -filter {ObjectClass -eq "User"} -Server $domain -Properties * |
    Where-Object {$_.mail -match $pattern} |
    select DistinguishedName, userPrincipalName, mail, ObjectClass |
    Export-csv -NoTypeInformation -Delimiter ";" -Path c:\Folder\file.csv -Append


  • #35735

    Bob McCoy

    I don't see where 'mail' is a property of Get-ADObject. And since that is the heart of your match statement, I can't make this work. You may want to use the EmailAddress property of the Get-ADUser cmdlet.

  • #35736

    Bob McCoy

    You really don't need to initialize you variables to $null.

    This ...

    $objForest = [System.DirectoryServices.ActiveDirectory.Forest]::GetCurrentForest()
    $DomainList = @($objForest.Domains | Select-Object Name)
    $Domains = $DomainList | foreach {$_.Name}

    ... can be reduced to this ...

    $domains = ([System.DirectoryServices.ActiveDirectory.Forest]::GetCurrentForest()).Name
  • #35801

    Recco Bucceri

    Awesome thanks bob, appreciate all the help!

    As far as the email attribute:

    Get-ADObject -filter {ObjectClass -eq "User"} -Server $domain -Properties * |
    Where-Object {$_.mail -match $pattern}

    I search for all properties and then single it out in the where-object {$_.Mail). I probably could change -properties * to -properties Mail.

  • #35809

    Dan Potter

    $re = "[a-z0-9!#\$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#\$%&'*+/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?"

    $user = (get-aduser someone).userprincipalname

    ([regex]::MAtch($user, $re, "IgnoreCase ")).success

  • #35810

    Bob McCoy
    $user = (get-aduser someone).userprincipalname

    This assumes that the UPN is the same as the email address, which is not universally the case.

  • #35817

    Dan Potter

    oops. try this.


You must be logged in to reply to this topic.