Free memory for all DC's in Forest

I am getting a bit more adventurous with my Powershell scripting education and want two combine to working scripts into one.

I’m seeking to discover all available free memory for all DC’s in our forest.

This one runs whatever Invoke-Command I want:

$DCs = foreach ($domain in ((get-adforest).domains)) {
  
    get-addomaincontroller -filter * -server $domain |
    sort hostname  | select -Property hostname -ExpandProperty hostname
}

$dc = New-PSSession -ComputerName $DCs -Credential Get-Credential

#Get Local Environment DC's and query for Web Server feature installation
Invoke-Command -Session $dc {
    Get-WindowsFeature -Name Web-Ftp-Server | select -Property PScomputerName,Installed,Name,SubFeatures
}

… while this Function gets the local servers available free memory:

Function Show-MemoryUsage {
[cmdletbinding()]
Param()
 
$os = Get-Ciminstance Win32_OperatingSystem
$pctFree = [math]::Round(($os.FreePhysicalMemory/$os.TotalVisibleMemorySize)*100,2)
 
if ($pctFree -ge 45) {
$Status = "OK"
}
elseif ($pctFree -ge 15 ) {
$Status = "Warning"
}
else {
$Status = "Critical"
}
 
$os | Select @{Name = "Status";Expression = {$Status}},
@{Name = "PctFree"; Expression = {$pctFree}},
@{Name  = "FreeGB";Expression = {[math]::Round($_.FreePhysicalMemory/1mb,2)}},
@{Name = "TotalGB";Expression = {[int]($_.TotalVisibleMemorySize/1mb)}},
@{Name = "Domain Controller";Expression = {($_.CSName)}}
  
}

How would I run a Function within my Invoke-Command script?

thank you kindly and have a great weekend!

If you want to run a locally defined function on a remote computer, you can pass the function definition as a script block via -ArgumentList and execute it using call operator.

function Test {
    Write-Output "From $env:ComputerName"
}

Invoke-Command -ComputerName servername -ScriptBlock {
    Param(
        [scriptblock]$Function
    )
    & $function
} -ArgumentList ${Function:test}

I tried to use your suggesiton but I don’t really have (or need) to run a [scriptblock] in the Invoke-Command. Just want to run the Function remotely.

This is what I came up with but it is wrong.

[PSSessions $dc already setup and running to all DC’s]

Invoke-Command -Session $dc {
    Param(
        $Function
    )
    & $function

} -ArgumentList ${Function:Show-MemoryUsage}

You can extend your thoughts,

Invoke-Command -ComputerName server -ScriptBlock ${function:Show-MemoryUsage}

See here for a few other possible alternatives as well, but @kvprasoon has given the most succinct and effective answer already. :slight_smile:

 

kvprasson I tried your construct but Invoke-Command cannot validate argument on parameter ‘scriptblock’

Function Show-MemoryUsage {
[cmdletbinding()]
Param()
 
$os = Get-Ciminstance Win32_OperatingSystem
$pctFree = [math]::Round(($os.FreePhysicalMemory/$os.TotalVisibleMemorySize)*100,2)
 
if ($pctFree -ge 45) {
$Status = "OK"
}
elseif ($pctFree -ge 15 ) {
$Status = "Warning"
}
else {
$Status = "Critical"
}
 
$os | Select @{Name = "Status";Expression = {$Status}},
@{Name = "PctFree"; Expression = {$pctFree}},
@{Name  = "FreeGB";Expression = {[math]::Round($_.FreePhysicalMemory/1mb,2)}},
@{Name = "TotalGB";Expression = {[int]($_.TotalVisibleMemorySize/1mb)}},
@{Name = "Domain Controller";Expression = {($_.CSName)}}
  
}

$DCs = foreach ($domain in ((get-adforest).domains)) {
  
    get-addomaincontroller -filter * -server $domain -Credential Get-Credential |
    sort hostname  | select -Property hostname -ExpandProperty hostname
}

$dc = New-PSSession -ComputerName $DCs #-Credential Get-Credential

#Get memory usage of all session computers
Invoke-Command -ComputerName $dc ${
    function:Show-MemoryUsage
}

…probably has to do with the kind of object that’s being passed to Invoke-Command, but I can’t think of any other way to run this working function to Remote computers

Thanks Joel, I’ll read it

You can’t have spaces in that usage, ${function:Show-MemoryUsage}.

This usage will behave like a Get-Content.

${function:prompt}
${variable:error}
${env:logonserver}

Great thanks kvprasoon, that worked. I was being a space cadet!

My revised code:

#create function
Function Show-MemoryUsage {
[cmdletbinding()]
Param()
 
$os = Get-Ciminstance Win32_OperatingSystem
$pctFree = [math]::Round(($os.FreePhysicalMemory/$os.TotalVisibleMemorySize)*100,2)
 
if ($pctFree -ge 45) {
$Status = "OK"
}
elseif ($pctFree -ge 15 ) {
$Status = "Warning"
}
else {
$Status = "Critical"
}
 
$os | Select @{Name = "Status";Expression = {$Status}},
@{Name = "PctFree"; Expression = {$pctFree}},
@{Name  = "FreeGB";Expression = {[math]::Round($_.FreePhysicalMemory/1mb,2)}},
@{Name = "TotalGB";Expression = {[int]($_.TotalVisibleMemorySize/1mb)}},
@{Name = "Domain Controller";Expression = {($_.CSName)}}
  
}

#get all DC's in the forest
$DCs = foreach ($domain in ((get-adforest).domains)) {
  
    get-addomaincontroller -filter * -server $domain |
    sort hostname  | select -Property hostname -ExpandProperty hostname
}

#create a new session for each of those DC's
$dc = New-PSSession -ComputerName $DCs -Credential Get-Credential

#Get memory usage of all session DC's
Invoke-Command  $dc ${function:Show-MemoryUsage} | select PSComputerName,TotalGB,PctFree | Export-Csv .\FreeMemDCs.csv -NoTypeInformation #ft -AutoSize

#remove all open Sessions
Get-PSSession | Remove-PSSession

I attempted a Calculated Expression for PSComputerName thus:

select  -Property @{Name=‘Domain Controller’;Expression={PSComputerName}}

…but returns blank. What am I missing here please?