Invoke-Command for a Function

I am trying to get common resources from a bunch of DCs ($DCs). I can run a function (called “Get-Resources”) on a local one and the Function works. How do I structure a Function, though, with Invoke-Command?

tried this but no multiple results:

$DCs | % {

Invoke-Command -ComputerName $DCs -ScriptBlock { {Function:Get-Resources}}
               
}  

If it is a custom function (written by you or someone else), then it needs to be available on each one of the servers in $DCs. If it is available, try this:

$DCs | % {
 
Invoke-Command -ComputerName $_ -ScriptBlock {Get-Resources}
               
}

I just noticed the ComputerName value is wrong as well. You are using For-EachObject, so you should use $_. I have made the correction in my previous post.

ah, not there’s too many DCs to copy that (Function) onto. Is there another method to leverage invoke-Command to gather essentially the same info, per server (mem, cpu, at least)?

You can take the contents of the function and pass it into the scriptblock as a string. Inside the scriptblock that’s running on the remote machine, you will create a new scriptblock from that string and then invoke it. If you need to pass arguments to the function then some changes would be required. Here’s a non-destructive demo you can run to test this. This assumes you have a variable that holds an array of server names

 
function say-hello {

    Write-Host Hello from $env:COMPUTERNAME
}

$servers = 'server1','server2','server3'

Invoke-Command -ComputerName $servers -ScriptBlock {
    Param($function)

    $sb = [scriptblock]::Create($function)
    $sb.Invoke()

} -ArgumentList (Get-Command say-hello).definition
1 Like

Copied and reedited my last reply. Ooo the colors are a little harsh for ```powershell formatting.

One way, with the variable in the local scope. It’s value is a scriptblock.

function hi { ‘hello’ }
invoke-command localhost $function:hi
hello

Or a script instead of a function:

“‘hello’” | set-content hi.ps1
invoke-command localhost hi.ps1
hello
1 Like

That works thank you!

I have this then:

$DCs = [DirectoryServices.ActiveDirectory.Forest]::GetCurrentForest() |
    Select-Object -ExpandProperty Sites |
        Select-Object -ExpandProperty Servers |
            Select-Object -ExpandProperty Name |
                **Sort-Object**

function Resources{  
                 param(  
                 $computername =$env:computername  
                 )  
                 # Processor utilization 
                 #Get-WmiObject -ComputerName $computer -Class win32_processor -ErrorAction Stop | Measure-Object -Property LoadPercentage -Average | Select-Object * 
                $cpu = gwmi win32_perfformatteddata_perfos_processor -ComputerName $computername| ? {$_.name -eq "_total"} | select -ExpandProperty PercentProcessorTime  -ea silentlycontinue  
                 # Memory utilization 
                 $ComputerMemory = Get-WmiObject -ComputerName $computername  -Class win32_operatingsystem -ErrorAction Stop 
                 $Memory = ((($ComputerMemory.TotalVisibleMemorySize - $ComputerMemory.FreePhysicalMemory)*100)/ $ComputerMemory.TotalVisibleMemorySize) 
                 $RoundMemory = [math]::Round($Memory, 2) 
                 # Free disk space 
                 $disks = get-wmiobject -class "Win32_LogicalDisk" -namespace "root\CIMV2" -computername $computername 
                 $results = foreach ($disk in $disks)  
                 { 
                 if ($disk.Size -gt 0) 
                 { 
                   $size = [math]::round($disk.Size/1GB, 0) 
                   $free = [math]::round($disk.FreeSpace/1GB, 0) 
                   [PSCustomObject]@{ 
                   Drive = $disk.Name 
                   Name = $disk.VolumeName 
                   "Total Disk Size" = $size 
                   "Free Disk Size" = "{0:N0} ({1:P0})" -f $free, ($free/$size) 
                   } } }     

                   # Write results 
                   Write-host "Resources on" $computername "- RAM Usage:"$RoundMemory"%, CPU:"$cpu"%, Free" $free "GB" 
                   }
Invoke-Command -ComputerName $DCs $function:Resources

(Notice where I put the Sort-Object. My variable has my DCs sorted but after my Invoke-Command, not really.

Is there a better place to put that Sort so my output is ordered alphabetically?

Worked great thanks Doug