Pass a variable as a parameter in Powershell

I'm trying to create a powershell script that will grab all Active Directory accounts that are enabled, and inactive for 90 days. The script will prompt the user to choose between querying computer or user accounts. Depending on the choice, it will pass it over to the main command as a variable.

The commands work correctly if I don't pass a variable.

I'm not sure if what I'm trying to do is possible.

Sorry for any bad code formatting. Just starting out.

    Clear-Host
    write-host "`nProgram searches for Enabled AD users account that have not logged in for more than 90 days. `nIt searches the entire domain and saves the results to a CSV file on users desktop." "`n"


    $choice = Read-host -Prompt " What do you want to search for Computer or Users Accounts`nType 1 for users`nType 2 for Computers`n`nChoice"



$account
if ($choice -eq 1){
   $account = UsersOnly 
   }
Elseif($choice -eq 2){
   $account = ComputersOnly
   }
Else{
   write-host "This is not an option `n exiting program"
   exit
   }



                $FileName = Read-Host -Prompt "What do you want to name the CSV file"
                $folderPath = "$env:USERPROFILE\Desktop\$FileName.csv"

                Search-ADAccount -AccountInactive -TimeSpan 90 -$account | Where-Object { $_.Enabled -eq $true } | select Name, UserPrincipalName, DistinguishedName | Export-Csv -Path $folderPath

1 answer

  • answered 2019-02-02 02:16 briantist

    Splatting is the way to achieve this. It's so named because you reference a variable with @ instead of $ and @ kind of looks a "splat".

    it works by creating a hashtable, which is a type of dictionary (key/value pairs). In PowerShell we create hashtable literals with @{}.

    To use splatting you just make a hashtable where each key/value pair is a parameter name and value, respectively.

    So for example if you wanted to call Get-ChildItem -LiteralPath $env:windir -Filter *.exe you could also do it this way:

    $params = @{
        LiteralPath = $env:windir
        Filter = '*.exe'
    }
    
    Get-ChildItem @params
    

    You can also mix and match direct parameters with splatting:

    $params = @{
        LiteralPath = $env:windir
        Filter = '*.exe'
    }
    
    Get-ChildItem @params -Verbose
    

    This is most useful when you need to conditionally omit a parameter, so you can turn this:

    if ($executablesOnly) {
        Get-ChildItem -LiteralPath $env:windir -Filter *.exe
    } else {
        Get-ChildItem -LiteralPath $env:windir
    }
    

    Into this:

    $params = @{
        LiteralPath = $env:windir
    }
    
    if ($executablesOnly) {
       $params.Filter = '*.exe'
    }
    
    Get-ChildItem @params
    

    or this:

    $params = @{}
    
    if ($executablesOnly) {
       $params.Filter = '*.exe'
    }
    
    Get-ChildItem -LiteralPath $env:windir @params
    

    With only 2 possible choices, the if/else doesn't look that bad, but as your choices multiply and become more complicated, it gets to be a nightmare.


    Your situation: there's one thing I want to note first. The parameters you're trying to alternate against are switch parameters. That means when you supply them you usually only supply the name of the parameter. In truth, these take boolean values that default to true when the name is supplied. You can in fact override them, so you could do Search-ADAccount -UsersOnly:$false but that's atypical.

    Anyway the point of mentioning that is that it may have been confusing how you would set its value in a hashtable for splatting purposes, but the simple answer is just give them a boolean value (and usually it's $true).

    So just changing your code simply:

    $account = if ($choice -eq 1) {
        @{ UsersOnly = $true }
    } elseif ($choice -eq 2) {
        @{ ComputersOnly = $true }
    }
    
    # skipping some stuff
    
    Search-ADAccount -AccountInactive -TimeSpan 90 @account
    

    I also put the $account assignment on the left side of the if instead of inside, but that's your choice.