How to create one input parameter that can receive empty or non-empty values

Viewed 568

I am trying to create function that will receive an argument as log file path.
I want this parameter to be able to receive string path or used as a [switch], without any arguments.

The reason I want to do it is because I have three scenarios I need to cover and I wanted to do it with only one parameter:
1. The parameter is not passed
2. The parameter is passed with empty argument
3. The parameter is passed with argument

Here is a script that demonstrate what I want:

function myFunc(){
    param(
       $LogFile = $null
    )

    # 1. PS > myFunc 
    if($LogFile -eq $null){  
    }

    # 2. PS > myFunc -LogFile
    if($LogFile -eq ""){
    }

    # 3. PS > myFunc -LogFile "C:\tmp\log.txt"
    else{ 
    }      
}

Is it possible to create such input parameter that can receive empty and non-empty values ?

When I run myFunc -LogFile I receive an error:

myFunc : Missing an argument for parameter 'LogFile'. Specify a parameter of type 'System.Object' and try again.
At line:1 char:8
+ myFunc -LogFile
+        ~~~~~~~~
    + CategoryInfo          : InvalidArgument: (:) [myFunc], ParameterBindingException
    + FullyQualifiedErrorId : MissingArgument,myFunc

This is because it is not set to [switch] and if I add the [switch] than I can't run myFunc -LogFile c:\tmp\file.txt:

myFunc : A positional parameter cannot be found that accepts argument 'C:\tmp\file.txt'.
At line:1 char:1
+ myFunc -LogFile C:\tmp\file.txt
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidArgument: (:) [myFunc], ParameterBindingException
    + FullyQualifiedErrorId : PositionalParameterNotFound,myFunc

I also tried to use [AllowNull()] and [AllowEmptyString()] but they still require to some char.
More information about the parameters can find here.

4 Answers

I don't think you can have a parameter acting like a switch as well as like string input. This is because if you try to use it like a switch it will complain that you didn't pass it any input:

myFunc : Missing an argument for parameter 'LogFile'. Specify a parameter of type 'System.Object' and try again.

One way to get the behavior you're looking for would be to have $LogFile as a switch and then have a second parameter that could take the string (which you wouldn't need to explicitly declare as the input would go to this parameter by the order its called in -- giving the impression it's being passed to -LogFile). Here's an example of that:

function myFunc{
    param(
       [switch]$LogFile,
       [string]$LogPath = $null
    )

    # 1. PS > myFunc 
    if ($LogFile -eq $false){
        "Function used without parameter"  
    }

    # 2. PS > myFunc -LogFile
    elseif ($LogFile -eq $true -and -not $LogPath){
        "Parameter used like a switch"
    }

    # 3. PS > myFunc -LogFile "C:\tmp\log.txt"
    else{
        "Parameter was $LogPath"     
    }      
}

myfunc
myfunc -logfile
myfunc -logfile "C:\tmp\log.txt"

To be honest though, scernario 2 is sort of not necessary on the assumption that all you want to do in this case is have a default path. In which case, you could just give $LogPath a default in the param() block. It's also probably not a good idea to be misleading about what is actually going on with the parameters (although the get-help documentation syntax block would expose that regardless).

Accept the $LogFile as a switch argument, then if it's present, just convert it's type to a string value, populating it with the value of the following argument, if present:

   param(
       [switch]
       $LogFile
   )

 if($LogFile)
 {
    #We neeed to change the variable type, so remove it
    Remove-Variable -Name "LogFile"
    #The remaining arguments are placed in $args array.
     if($args.Count -gt 0)
     {

        $LogFile = [String]$args[0]
     }
     else {
        $LogFile = [String]""
     }
 }
 # 1. PS > myFunc
 else {
    "# 1. PS > myFunc "
}
# 2. PS > myFunc -LogFile
if($LogFile -eq ""){
        "LogFile is empty"
}

# 3. PS > myFunc -LogFile "C:\tmp\log.txt"
elseif ($LogFile -is [String]){ 
    "logFile is $logFile"
}      
function cookieMonster($ChocolateChipCookie){
   if ([string]::IsNullOrEmpty($chocolateChipCookie)){
         write-host "Hey wheres my Cookies! "
   }
   else {
         write-host "MMMMM COOKIES! NOM NOM NOM"
   }       
}

cookieMonster -ChocolateChipCookie C:\cookiejar\cookie.txt

This answer is inspired by the Legendary Mark Wragg above:

function cookieMonster{
    param(

       [switch] $ChocolateChipCookie,
        [string] $Crumbs = $null
    )

# The function without parameters
if($ChocolateChipCookie -eq $false){
    write-host "no cookies;("
}

# The parameter is not passed
elseif ($ChocolateChipCookie -eq $true -and -not $Crumbs) {
    Write-Host "Aw just crumbs!"
}
# The parameter is passed with argument
else {
    write-host "MMMMM COOKIES! NOM NOM NOM"
}


}

cookieMonster  -ChocolateChipCookie  C:\cookiejar\cookie.txt

The $ChocolateChipCookie is defined as a switch parameter. Then the value given to the switch parameter is created as string parameter called $crumbs.

The if block checks if the function was called without a switch and writes a message.

The elseif block checks if the function was called with a switch which has no value.

The else block writes a message if non of the above conditions are met.

Related