Fabricating a custom -Filter in my Advanced Function

This topic contains 5 replies, has 3 voices, and was last updated by  Micah Battin 3 years, 6 months ago.

  • Author
  • #13575

    Micah Battin

    I have an Advanced Function that is designed to stream packets to me and they come into my NIC, similar to Wireshark. The problem is that I want to implement a -Filter parameter in my function rather than piping the whole function to Where-Object.

    At first glance, I thought I would get away with setting a a $filter paramater as a scriptblock and where I am streaming the object in one at a time, piping THAT object to Where-Object like this:
    $Packet Where-Object -FilterScript $Filter

    This however didn't work as I had planned. I am going to spare the long explanation of trial and error for the time being. Does anyone know of resources out there for implementing my own -Filter Parameter? I have searched for the last hour and a half and had no luck.

  • #13580

    Micah Battin

    Never Mind. I tried an additional test and it succeeded. So the Fundamental question that I was asking has been solved. This is the test that I ran and succeeded with:

    Function Test {

    Begin {
    Process {

    $Packet = New-Object PSObject -Property @{
    Name = "MyStuff"
    Address = ""
    Port = 135
    Notes = "This is a test."

    If ($Filter) {
    $Packet | Select-Object Name,Address,Port,Notes | Where-Object $Filter
    Else {
    $Packet | Select-Object Name,Address,Port,Notes
    End {

    Test -Filter {$_.Name -like "Stuff"}
    # No Results
    Test -Filter {$_.Name -like "*Stuff*"}
    # Results

    I lied... There is a followup question that comes to mind. With the -filter in Get-ADUser, I can specify
    {SamAccountName -eq "MyUserName"}
    Rather than
    {$_.SamAccountName -eq "MyUserName"}

    Does anyone have an idea on how I can mimic that functionality in the test code above?

  • #13581

    Dave Wyatt

    Get-ADUser's filter is much more complex. It accepts a string, not a ScriptBlock, and it has code to parse that string and turn it into an LDAP filter behind the scenes. Writing your own code to parse a complex expression and evaulate it against an input object would be a lot of work, with the only real benefit being that the user can save three characters of typing by eliminating $_.

  • #13583

    Micah Battin

    I understand. I guess the bigger concern of mine is that trying to remember several different -filter syntax's for different commands might be a little too much with their already high stress from a heavy workload. I am just trying to match it to AD because it is what they are used to. Now that I know there is no "easy" way to do it, I will likley go on a glorious adventure developing a code snippet to handle it in the way that I desire.

    Thanks for all your help!

  • #13576

    Don Jones

    So, I am completely not understanding what you're asking. I think you probably need to share some code snippets of what you're doing.

    As far as implementing your own -Filter parameter... that's easy. Doing something with it depends entirely on what your code is doing. I mean, there's no built-in "here's how to write a filter." For example,

    function foo {
      Get-Something | Where-Object -Filter $filter

    Essentially works, but I've no idea if that's meaningful in what you're trying to do. And I should point out that this is not functionally all that different from piping the whole function to Where-Object, if your function is normally outputting one object at a time to the pipeline. A filter is really only meaningful in a function if it can prevent data from entering PowerShell at all, a la the -Filter on Get-WmiObject. Once you're "filtering using PowerShell," it doesn't necessarily matter where you do it (again, all things being equal – not seeing your code it's hard to make definitive statements).

  • #13577

    Dave Wyatt

    I doubt the performance will be any better than using Where-Object, but you can do something like this:

    function YourFunction
        param (
            if ($null -eq $Filter -or $Filter.Invoke($InputObject))
                # Object passed your filter (or no filter was specified); do something here

    With the code written like that, the two following commands would produce identical results:

    $strings = '1','22','333','4444','55555'
    $strings | YourFunction | Where-Object { $_.Length -gt 3 }
    $strings | YourFunction -Filter { $_.Length -gt 3 }

You must be logged in to reply to this topic.