Free memory for all DC's in Forest

Welcome Forums General PowerShell Q&A Free memory for all DC's in Forest

This topic contains 8 replies, has 3 voices, and was last updated by

 
Participant
7 months, 1 week ago.

  • Author
    Posts
  • #123362

    Participant
    Topics: 110
    Replies: 233
    Points: 70
    Rank: Member

    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!

  • #123402

    Moderator
    Topics: 8
    Replies: 890
    Points: 2,744
    Helping Hand
    Rank: Community Hero

    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}
    
  • #123728

    Participant
    Topics: 110
    Replies: 233
    Points: 70
    Rank: Member

    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}
  • #123809

    Moderator
    Topics: 8
    Replies: 890
    Points: 2,744
    Helping Hand
    Rank: Community Hero

    You can extend your thoughts,

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

      Participant
      Topics: 110
      Replies: 233
      Points: 70
      Rank: Member

      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

    • #125196

      Moderator
      Topics: 8
      Replies: 890
      Points: 2,744
      Helping Hand
      Rank: Community Hero

      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}
      
    • #125261

      Participant
      Topics: 110
      Replies: 233
      Points: 70
      Rank: Member

      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?

  • #123981

    Participant
    Topics: 2
    Replies: 442
    Points: 923
    Helping Hand
    Rank: Major Contributor

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

     

    • #125010

      Participant
      Topics: 110
      Replies: 233
      Points: 70
      Rank: Member

      Thanks Joel, I'll read it

The topic ‘Free memory for all DC's in Forest’ is closed to new replies.