简体   繁体   中英

Powershell AD Syntax - If Statement is duplicating a string

New scripter with hopefully an easy proofread.

I made an Powershell Active Directory script that processes people on Leave of Absence (LOA) within my organization from a daily CSV file I get.

In summary my problem segment should:

  • Check the $Line variable's currentStatus if that employee is "On Leave"
  • Disable that Active Directory account.
  • Grab that AD account's 'Description' field and look for the string part "LOA - " and add that ONLY if it is missing. Problem is that if that field already has "LOA - " in the description, it puts another one... and another, so on.

Example:

  • Description (Good): LOA - Chef
  • Description (Bad): LOA - LOA - Chef
  • Description (Please NO): LOA - LOA - LOA - Chef
  • Etc.

I'm fairly certain the problem is with this line here but I can't figure out how to fix it.

If ($null -ne ($newDescript |? {$loaPhrases -notcontains $_}))

$loaPhrases = "LOA -|LOA-|LOA - |LOA- |LOA - LOA - "

ElseIf ($Line.currentStatus -eq "ON LEAVE") 
{
    #Add 'LOA - ' to description and disable AD
    Set-ADUser $User.samAccountName -Enabled 0
    'Disabled AD'

    $Description = Get-ADUser $User.samAccountName -Properties Description | Select-Object -ExpandProperty Description
    $newDescript = $Description.substring(0, $Description.IndexOf('-')+1)
    If ($null -ne ($newDescript | ? {$loaPhrases -notcontains $_}))
    {
        $Description = "LOA - " + "$Description"
        $Description = $Description.trim()
        Set-ADUser $user.samAccountName -Description $Description
    }  
}                                          

It looks like you're overcomplicating it a bit. Try the -match statement for a regex matching of your $loaPhrases.....

if ($description -notmatch $loaPhrases)

This could do with fancier editing and checks, but basically checks your regex string (separated by |, as you have) for the loa string. If it's not there, it does your addition of the "LOA - " part.

Edit: Adding option to simply look at the start of a string

As Steven pointed out in the comments, it's likely you're looking for a LOA string at the start of the description to determine whether you need to add one in. As all your LOA strings begin with "LOA", you could simply check to ensure it doesn't start with "LOA", to determine if you need to add it in.

if (!($description.startswith("LOA")))

The ! flips the boolean value returned by $description.startswith("LOA") , so if it does start with "LOA", it returns false, and if it doesn't start with "LOA", it returns true, and enters the if statement.

As an aside, earlier in, you set -Enabled 0 . My recommendation, for readability, is to change that to -Enabled $false , as it indicates clearly you're disabling the account, rather than setting it to an integer (even though this works / 0 usually being "false").

Building on Guy S's Helpful Answer , and considering you are new to this I wanted to make a few extra points.

Considering you are changing more than 1 property you might consider using a different approach to setting the user object. In the case of the Active Directory cmdlets there's an instancing capability that I really like. Such an approach might look something like below:

ElseIf ($Line.currentStatus -eq "ON LEAVE") 
{    
    # Get and store the instance in a variable:
    $ADUser = Get-ADUser $User.samAccountName -Properties Description
    
    $ADUser.Enabled = $false # Change the desired properties...
    Write-Host 'Disabled AD'

    If( $ADUser.Description -notmatch $loaPhrases )
    {
        $ADUser.Description = "LOA - " + $ADUser.Description.Trim()
    }

    # After changing properties run a single set command citing -Instance:
    Set-ADUser -Instance $ADUser    
}

Notice, I used Write-Host instead of just quoting "Disable AD". In a top-down script, it's probably not a big deal but if this code were inside a function that string would get returned. That causes variant arrays, unexpected function returns, and associated problems. Again, not necessarily a problem here, but you'll want to be aware of that going forward. In fact, it's a common confusion as people get more advanced with PowerShell.

I have seen anomalies where -Instance doesn't like null values. However, the Description attribute doesn't seem to have that problem. Splatting may be another option and is super useful in situations even slightly more complex than this... Read more about splatting here ,

I also want to talk a little more about your original code and the subsequent samples.

First -contains , -in and their "not" variants don't work well on strings. For example, "string" -contains "ing" will return "False". So, conceptually the approach is a bad match for what you were trying to do. Most would use -match which is a RegEx based approach.

Note: For simple stuff -Like can use a less robust wildcard approach. In your case -match is your best bet because of the variation in the match string"

-contains and -in are great for checking arrays and other collections:

$Array = "One", "Two"

$Array -contains "one"

"one" -in $Array

Above, both -contains and -in will return "True"

Given the indication that you want to search the beginning of the string, I'd modify the RegEx to use the "^" anchor like: $loaPhrases = "^LOA -|^LOA-|^LOA - |^LOA- |^LOA - LOA - " Come to think of it a simple "^LOA" may do the trick. Regarding Guy's answer, I'd avoid .StartsWith() or for that matter .EndsWith() only because they are case sensitive.

Lastly, I'll point out the comparison to $null is unnecessary even besides the other issues.

$Array = "One", "Two"
If( ( $Array | Where-Object{ $_ -eq "Three"} ) ){
    "Something"
}

In the above example "Something" will not get echoed to the screen. If you change "Three" to "Two" it will.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM