Daikyu
Daikyu

Reputation: 331

Trying to pass an advanced function as a function argument in Powershell

I have a CSV file with computer names. I import them and want to use each value to do something with.

$computerNames = import-csv -Path "C:\Users\fakePath\Desktop\Programming\Powershell\remoteAddPrinters\computers.csv" -header "Computers"

function Iterate-CSV {
    param (
        # Parameter help description
        [Parameter(Mandatory=$true)]
        [array]
        $csvFilePath,

        [scriptblock]$functionCall #?
    )
    foreach ($computer in ($csvFilePath).Computers) { # Computer is the argument used in other functions.

        Write-Host $functionCall.Invoke($computer)
    }
}

This takes a csv file as a param then loops over it. trying to get this function passed as a parameter

function Add-NetworkPrinter {
    [CmdletBinding()]
    param (
        # Parameter help description
        [Parameter(Mandatory=$true, Position=0)]
        [String]
        $computerName
    )
    
    begin {
        $addPrinterCue = "\\printServer\printCue"
    }
    
    process { # This is a non-terminating error and cannot be handled by try/catch
        Write-Output "$addPrinterCue && $computerName"
        # invoke-command -ComputerName $computerName -scriptBlock {
        #     # cmd.exe /c rundll32 printui.dll,PrintUIEntry /gd /n$addPrinterCue
        #     cmd.exe /c rundll32 printui.dll,PrintUIEntry /ga /n$addPrinterCue /q
        #     Restart-Service -Name Spooler -Force
        #                                     #Creates error to handle
        # } -Credential $domainCredentials  #-ErrorVariable errmsg 2>$null
    }
    
    end {
        Write-Output "Successfully added printer to $computerName"
    }
}

That way i dont have to write another foreach loop to do other tasks syncronously using values within the CSV, i can just make functions taking one argument, the iteration variable

Upvotes: 0

Views: 171

Answers (3)

Daikyu
Daikyu

Reputation: 331

Instead of creating an Advanced Function named Add-NetworkPrinter, I just created a scriptblock, as @Andrey pointed out while keeping my advanced function that iterates through values of the CSV file.

$computerNames = import-csv -Path "C:\fakePath\computers.csv" -header "Computers"

function Iterate-CSV {
    param (
        # Parameter help description
        [Parameter(Mandatory=$true)]
        [array]
        $csvFilePath,
        [scriptblock]$functionCall
    )
    foreach ($computer in ($csvFilePath).Computers) { 
        Write-Host $functionCall.Invoke($computer)
    }
}

$addNetworkPrinter = [scriptblock]{ 
    param ($computer)
    $addPrinterCue = "\\printServer\printCue"
    Write-Output "$addPrinterCue && $computer"
    # invoke-command -ComputerName $computerName -scriptBlock {
    #     # cmd.exe /c rundll32 printui.dll,PrintUIEntry /gd /n$addPrinterCue
    #     cmd.exe /c rundll32 printui.dll,PrintUIEntry /ga /n$addPrinterCue /q
    #     Restart-Service -Name Spooler -Force
    #                                     #Creates error to handle
    # } -Credential $domainCredentials  #-ErrorVariable errmsg 2>$null
}

$restarComputers = [scriptblock]{
    param (
        [Parameter(Mandatory=$true, Position=0)]
        [string]
        $computer
    )
    Write-Output "Restarting computer $computer"
    # Restart-Computer -ComputerName $computer -Credential $domainCredentials -Force
}

Then I just call my Iterate-CSV function by providing the path to csv as param1 and scriptblocks that use the same values for param2. Thanks for the ScriptBlock Info!

Iterate-CSV -csvFilePath $computerNames -functionCall $addNetworkPrinter
Iterate-CSV -csvFilePath $computerNames -functionCall $restarComputers

Upvotes: 0

Mathias R. Jessen
Mathias R. Jessen

Reputation: 174815

To reference the underlying scriptblock definition of a registered function, use the function: drive prefix to pass it as a variable:

Iterate-Csv ... -scriptBlock ${function:Add-NetworkPrinter}

Upvotes: 1

Andrey
Andrey

Reputation: 4356

You'll need to pass a scriptblock that calls your function.

$func = [scriptblock]{ 
    param ($arg)
    Add-NetworkPrinter $arg 
}

Iterate-CSV -csvFilePath ... -functionCall $func

Upvotes: 1

Related Questions