Variable contents changed by function it is passed to - what am I forgetting?

Welcome Forums General PowerShell Q&A Variable contents changed by function it is passed to - what am I forgetting?

This topic contains 2 replies, has 2 voices, and was last updated by

4 years, 4 months ago.

  • Author
  • #20368

    Points: 32
    Rank: Member

    I recently (re)wrote a coworker's script into a slightly more properly constructed function. One of the function's parameters takes an object, a collection/array of psobjects to be specific. The function does some filtering, and then tweaks the value of one property on certain elements of the collection. In testing, I'm importing a CSV to a variable, and then calling the function as such:

    $collection = $import-csv c:\temp\blah.csv
    get-hcpatchlists -list $collection

    I'm not sure I've written a script at all like this before and so I was quite surprised to find that after running the function, the array in $collection had been modified. As the title of the topic says, am I forgetting something fundamental?

    please forgive the gratuitous Write-Verboses. I was trying to figure out why the function was behaving differently the second time I ran it. I'm not a fan of what the script is doing in terms of output, but that's a battle for another day.

    function Get-HCPatchLists {
        param (
            # The object representing the list SIDv1
            # A path to save the files to
            [ValidateScript({Test-Path $_})]
            $netpath = "\\myserver\somepath\ServerPatchList\"
    begin {
        $excludes = ("Manual-Snowflakes","Linux","Shutdown Pending","Exempt","HCLIB","ESX Server","Departmental","Lab patching","Special Requirements","M 3,6,9,12")
        # Make sure that $netpath ends with a backslash
        If (-not ($netpath.endswith("\"))){
            $netpath += "\"   
        write-verbose $netpath
    process {
        # Filter out the patching schedules we don't want to deal with.
        $list = $list | Where-Object {$excludes -notcontains $_.PatchSchedule} | Where-Object {$_.Decommissioned -ne $true} 
        Write-Verbose "$($list.count) entries after filtering"
        foreach ($server in $list) {
            if ($server.PatchSchedule -eq "") {
                Write-Verbose "$($server.title) not categorized"
                $server.PatchSchedule = "ZZ-to be categorized"
            if ($server.domain -eq "") {
                Write-verbose "De-nulling $($server.title)'s domain"
                $server.domain = "Unknown"
            #Write-verbose "old domain: $($server.domain)"
            if ($server.domain -eq "ECOM") {
            #Write-Verbose $server.Cluster
    		    $server.cluster = ($server.Cluster).replace("Cluster","")
            #Write-Verbose $server.Cluster
    			$server.domain += "-$($server.cluster)"
            $path = "$netpath$($server.domain)-$($server.patchschedule).txt"
            try {
    		    #write-output "$name $patchstr"
    			out-file -filepath $path -append -inputobject $($server.title)
    		catch {
                write-verbose "error with $name : $_" 

    Is this expected behavior?

  • #20370

    Points: 0
    Rank: Member

    Yep, that's normal. There are two different ways you could attempt to modify a parameter. First, there's assigning to the variable itself:

    function Test-Something
        param ($TheParameter)
        $TheParameter = 'A new value'

    In this case, the "A new value" string would not be seen by the caller. However, another option is that you could modify the object referred to BY the parameter:

    function Test-Something
        param ([hashtable] $Hashtable)
        $hashtable['SomeNewKey'] = 'Some New Value'

    In this case, the caller would see the new key / value pair added to their hashtable. This is because the parameter variable inside the function and the variable that the caller passes to the function refer to the same object in memory, rather than a copy. This is true for all reference types (pretty much everything except for numeric values, Booleans, enums, with a few other exceptions that you may not run into in PowerShell.)

  • #20417

    Points: 32
    Rank: Member

    Thanks! That make sense!

    The simple solution is to leave the object alone, and perform the text manipulation with a variable that is only in the function's scope.

    Put another way, variables that "contain" objects, are really variables that "point to" objects.

The topic ‘Variable contents changed by function it is passed to - what am I forgetting?’ is closed to new replies.

denizli escort samsun escort muğla escort ataşehir escort kuşadası escort