37

I'm trying to read the event log for a security audit for all users except two, but is it possible to do that with the -notlike operator?

It's something like that:

Get-EventLog -LogName Security | where {$_.UserName -notlike @("*user1","*user2")}

I have it working for a single user, like:

Get-EventLog -LogName Security | where {$_.UserName -notlike "*user1"}

8 Answers 8

41

V2 at least contains the -username parameter that takes a string[], and supports globbing.

V1 you want to expand your test like so:

Get-EventLog Security | ?{$_.UserName -notlike "user1" -and $_.UserName -notlike "*user2"}

Or you could use "-notcontains" on the inline array but this would only work if you can do exact matching on the usernames.

... | ?{@("user1","user2") -notcontains $_.username}

Sign up to request clarification or add additional context in comments.

1 Comment

You can also reference the list of usernames to filter out via a variable: ?{$users -notcontains $_.username}
16

I think Peter has the right idea. I would use a regular expression for this along with the -notmatch operator.

Get-EventLog Security | ?{$_.Username -notmatch '^user1$|^.*user$'}

Comments

8

In order to support "matches any of ..." scenarios, I created a function that is pretty easy to read. My version has a lot more to it because its a PowerShell 2.0 cmdlet but the version I'm pasting below should work in 1.0 and has no frills.

You call it like so:

Get-Process | Where-Match Company -Like '*VMWare*','*Microsoft*'
Get-Process | Where-Match Company -Regex '^Microsoft.*'

filter Where-Match($Selector,[String[]]$Like,[String[]]$Regex) {

    if ($Selector -is [String]) { $Value = $_.$Selector }
    elseif ($Selector -is [ScriptBlock]) { $Value = &$Selector }
    else { throw 'Selector must be a ScriptBlock or property name' }

    if ($Like.Length) {
        foreach ($Pattern in $Like) {
            if ($Value -like $Pattern) { return $_ }
        }
    }

    if ($Regex.Length) {
        foreach ($Pattern in $Regex) {
            if ($Value -match $Pattern) { return $_ }
        }
    }

}

filter Where-NotMatch($Selector,[String[]]$Like,[String[]]$Regex) {

    if ($Selector -is [String]) { $Value = $_.$Selector }
    elseif ($Selector -is [ScriptBlock]) { $Value = &$Selector }
    else { throw 'Selector must be a ScriptBlock or property name' }

    if ($Like.Length) {
        foreach ($Pattern in $Like) {
            if ($Value -like $Pattern) { return }
        }
    }

    if ($Regex.Length) {
        foreach ($Pattern in $Regex) {
            if ($Value -match $Pattern) { return }
        }
    }

    return $_

}

Comments

7

don't use -notLike, -notMatch with Regular-Expression works in one line:

Get-MailBoxPermission -id newsletter | ? {$_.User -NotMatch "NT-AUTORIT.*|.*-Admins|.*Administrators|.*Manage.*"}

2 Comments

I'm curious, what is the purpose of the '.'s in this example?
A one-liner FTW.
4

Easiest way I find for multiple searches is to pipe them all (probably heavier CPU use) but for your example user:

Get-EventLog -LogName Security | where {$_.UserName -notlike "*user1"} |  where {$_.UserName -notlike "*user2"}

Comments

2

Scenario: List all computers beginning with XX1 but not names where 4th character is L or P

Get-ADComputer -Filter {(name -like "XX1*")} | Select Name | Where {($_.name -notlike "XX1L*" -and $_.name -notlike "XX1P*")}

You can also count them by enclosing the above script in parens and adding a .count method like so:

(Get-ADComputer -Filter {(name -like "XX1*")} | Select Name | Where {($_.name -notlike "XX1L*" -and $_.name -notlike "XX1P*")}).count

Comments

1

Using select-string:

Get-EventLog Security | where {$_.UserName | select-string -notmatch user1,user2}

1 Comment

Since the code in the question filters names that end with user1 or user2 (-notlike @("*user1","*user2")), for -Pattern this should pass user1$,user2$ or, more concisely, user[12]$. Otherwise, this will exclude names like user123, for example.
0
$listOfUsernames = @("user1", "user2", "etc", "and so on")
Get-EventLog -LogName Security | 
    where { $_.Username -notmatch (
        '(' + [string]::Join(')|(', $listOfUsernames) + ')') }

It's a little crazy I'll grant you, and it fails to escape the usernames (in the unprobable case a username uses a Regex escape character like '\' or '(' ), but it works.

As "slipsec" mentioned above, use -notcontains if possible.

1 Comment

Thanks Peter.. That's also a great alternative!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.