My first functions

This topic contains 4 replies, has 2 voices, and was last updated by Profile photo of Jarek C. Jarek C. 1 year, 9 months ago.

  • Author
    Posts
  • #22577
    Profile photo of Jarek C.
    Jarek C.
    Participant

    Since I am repeating a lot of code in my script I decided it may be worth creating functions for simplification. Yep. Not as easy as I thought. First I defined all my functions below the code that is calling them so lots of red text came back. I moved the functions to the top so it's better now but still getting issues. E.g. one of my variables reads text from a file with Get-Content giving System.String. Then another variable, lets call it $match goes through that text and selects only the lines that match certain condition. System.String again. Now I pass the variable to my function
    Function ($match){
    do sth....
    }
    When I call $match once it gets into the function to check it's value I get not only the lines matching my condition but also the path to the .txt file and Get-Member returns System.String and System.Object at the same time.
    No idea how the file path got into my $match variable and how to get it out from there.

  • #22580
    Profile photo of Dave Wyatt
    Dave Wyatt
    Moderator

    We'd have to see more code, but I suspect that you're running into other commands that are sending something to the output stream. It's a common gotcha in PowerShell until you get a feel for it. For example, let's say you're writing a function that for whatever reason, creates a new file and then outputs a number. The caller of the function is expecting just a number in the result:

    function Do-Something
    {
        $guid = [guid]::NewGuid().Guid
        New-Item $env:temp\$guid.txt
    
        return 5
    }
    
    $result = Do-Something
    

    $result is actually going to be an array containing a FileInfo object and the number 5, because New-Item also creates output. In your functions, you need to identify these spots and prevent them from polluting your output stream. There are three ways you can do this:

    – Assign the result of a command to a variable. You can assign to $null if you just want to discard the result.
    – Cast the result of a command to type [void]. You typically have to put parentheses around the whole command for that to work.
    – Pipe a command to Out-Null. This tends to be much slower than the other options, but looks nicer.

    Of the three, I tend to stick to "$null = " for performance reasons. So the revised function might look like this:

    function Do-Something
    {
        $guid = [guid]::NewGuid().Guid
        $null = New-Item $env:temp\$guid.txt
    
        return 5
    }
    

    I made a blog post on how to identify these commands some time ago: https://davewyatt.wordpress.com/2014/06/05/tracking-down-commands-that-are-polluting-your-pipeline/

  • #22588
    Profile photo of Jarek C.
    Jarek C.
    Participant

    Ah but in your example the issue comes up within {} of your function but in mine it's before it even gets there as $match is a parameter I want to pass to the function and the only time it's hit is where I declare that
    $match = $list | where {$_ -match 'ABC'} | gm – returns string – tested with setting a break point

    to select all lines within another variable I declared before declaring $match

    $list = Get-Content '.\test.txt' | gm – returns string – tested with setting a break point

    That $match then shows up when declaring parameters in

    Function Do-Something($match){ – tested with setting a break point
    ... }
    I set breakpoints after each of this lines too so I can read the value after the line runs not to get confused with it's value from the previous run.
    Saying that, before the Do-Something function I have a few other functions where one checks for a set of folders if they exist or not and creates them when needed.
    Somehow a path to one of the folders slips into my $match variable so when I call it before the Do-Something function gets processed after being called I get
    c:\test\Testfolder
    some text ABC
    some more text ABC
    I thought variables declared within a function live only within that function but it turns up it isn't so. I'm guessing that a variable declared a couple of function before gets into my Do-Something and messes things up.

  • #22589
    Profile photo of Dave Wyatt
    Dave Wyatt
    Moderator

    I'd need to see your full code to troubleshoot. I still say that the cause of this is some command sending output that you're not preventing, until I have some reason to believe otherwise. 🙂

  • #22595
    Profile photo of Jarek C.
    Jarek C.
    Participant

    Silly as it is I cannot publish the whole code due to some company policy even if completely harmless but thanks to your advise I'm moving forward.

You must be logged in to reply to this topic.