Advanced Function Optional Parameter Problem

This topic contains 4 replies, has 4 voices, and was last updated by  Istvan Szarka 4 years, 1 month ago.

  • Author
  • #16331

    Istvan Szarka


    I've written an advanced function that creates one or more VMs. I have a mandatory parameter and many optional, with some default values.
    The problem is with the optional parameters that have no default values.
    For example, there is a SwitchName parameter that is optional and has no default value, because I don't always want a new VM to connect to a switch.
    However, if I don't supply any value to it, I get this error, even if I use [AllowEmptyString()] and [AllowNull()] in the PARAM block:

    New-VM : Cannot validate argument on parameter 'SwitchName'. The argument is null or empty. Provide an argument that is not null or empty, and then try the command again.

    I want the VMs to connect to a switch only if I supply the name of a switch, otherwise I don't want them to connect anywhere. How can I do this?
    These are the relevant snippets from my code (sorry for the formatting, it gets messed up whatever I do):

    #Some of the parameters:
    #And so on
            foreach ($name in $VMName)
                    $params = @{Name                          = $name
                                             MemoryStartupBytes = $MemoryStartupBytes
                                             Generation                  = 2
                                             NewVHDPath             = "$VHDFolder\$name\$name.vhdx"
                                             NewVHDSizeBytes    = $VHDSizeBytes
                                             BootDevice                  = $BootDevice
                                             ComputerName         = $ComputerName
                                             Path                              = $VMFolder
                                             SwitchName               = $SwitchName}
                    New-VM @params
                    $params = @{VMName                              = $name
                                              DynamicMemoryEnabled = $true
                                              MinimumBytes                    = $MemoryMinimumBytes
                                              ComputerName                 = $ComputerName}
                    Set-VMMemory @params
  • #16332

    Don Jones

    You need to put some logic in your script to not provide the SwitchName parameter is $SwitchName is null.

    if ($SwitchName) { $params.Add('SwitchName',$SwitchName) }

    Something along those lines.

    The [AllowNull()] means YOUR FUNCTION will accept a null value from $SwitchName. That doesn't mean New-VM will do so.

  • #16333

    Bjorn Houben

    How do you call the function?

  • #16334

    Dave Wyatt

    The problem is probably when you pass a null / empty value to the New-VM cmdlet, based on what I can see so far. You'd need to construct your $params hashtable so that only the defined parameters are in it when you call New-VM. Something like this:

    $params = @{
        Name               = $name
        MemoryStartupBytes = $MemoryStartupBytes
        Generation         = 2
        NewVHDPath         = "$VHDFolder\$name\$name.vhdx"
        NewVHDSizeBytes    = $VHDSizeBytes
        BootDevice         = $BootDevice
        ComputerName       = $ComputerName
        Path               = $VMFolder
    if ($SwitchName) { $params['SwitchName'] = $SwitchName }
    New-VM @params

    Also, you'll want to get away from using ValueFromPipeline in combination with String parameters. Any object can be represented as a string, which will give you some crazy results when you start trying to pipe objects to this function. Based on what I see so far, ValueFromPipelineByPropertyName should be all you need.

  • #16337

    Istvan Szarka

    Thank you a lot, it works! I haven't encountered this amazing technique yet.
    Thank you for the advice on pipeline imput too!

You must be logged in to reply to this topic.