Search code examples
powershellpowercli

Pass variables to function


I have 2 functions. The functions need to pass a few earlier declared variables like this:

Function variable1, variable2

Now I've tried doing param with [ref] without success.

Here's the code for one of the functions. In this case the variables that are declared earlier are $wincluster and $vmhostwin.

function deploytemplatewin {
    foreach ($image in $winimage) {
        $templatename =  $image, $wincluster -join "_"
        $vcdatastore = $vc + "_vm_template_01"
        try {
            Get-Template $templatename -ErrorAction Stop;
            $TemplateExists = $true
        } catch {
            $TemplateExists = $false
        }
        if ($TemplateExists -eq $false) {
            Write-Log -Message "$($templatename) template was copied to cluster $($wincluster) on vCenter $($vc)"
            New-VM -Name $templatename -VMHost $vmhostwin -Datastore $vcdatastore -Location (Get-Folder -Name WinTemplates) |
                Set-VM -ToTemplate -Confirm:$false
        } elseif ($TemplateExists -eq $true) {
            Write-Log -Message "Template $($templatename) already existed in cluster $($wincluster) on vCenter $($vc)"
        }
    }
}

Worst case, I can explicitly state the variables in the function and it works.


Solution

  • If you want a function with parameters you need to define the parameters. You may also want to use the canonical Verb-Noun form for your function name (see here for a list of approved verbs).

    Simple approach:

    function Deploy-WindowsTemplate($Cluster, $VMHost) {
        foreach ($image in $winimage) {
            $templatename = $image, $Cluster -join "_"
            ...
        }
    }
    

    More advanced approach:

    function Deploy-WindowsTemplate {
        [CmdletBinding()]
        Param(
            [Parameter(Mandatory=$true)]
            [string]$Cluster,
            [Parameter(Mandatory=$true)]
            [string]$VMHost
        )
    
        foreach ($image in $winimage) {
            $templatename = $image, $Cluster -join "_"
            ...
        }
    }
    

    If you want you could also go without parameters and use the automatic variable $args, although I wouldn't recommend that.

    function Deploy-WindowsTemplate {
        foreach ($image in $winimage) {
            $templatename = $image, $args[0] -join "_"
            ...
        }
    }
    

    Note, however, that when calling a function parameter/argument values are separated by whitespace, not commas. They can be passed as positional parameters (by default in the order the parameters were defined)

    Deploy-WindowsTemplate $wincluster $vmhostwin
    

    or named parameters

    Deploy-WindowsTemplate -Cluster $wincluster -VMHost $vmhostwin
    

    Comma-separated values are passed as a single array argument.

    Deploy-WindowsTemplate $wincluster, $vmhostwin
    #                      ^^^^^^^^^^^^^^^^^^^^^^^
    #                           one argument!