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
3 weeks, 4 days ago.

  • Author
    Posts
  • #123362

    Participant
    Points: 71
    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

    Participant
    Points: 832
    Helping Hand
    Rank: Major Contributor

    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
    Points: 71
    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

    Participant
    Points: 832
    Helping Hand
    Rank: Major Contributor

    You can extend your thoughts,

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

      Participant
      Points: 71
      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

      Participant
      Points: 832
      Helping Hand
      Rank: Major Contributor

      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
      Points: 71
      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
    Points: 275
    Helping Hand
    Rank: Contributor

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

     

    • #125010

      Participant
      Points: 71
      Rank: Member

      Thanks Joel, I'll read it

You must be logged in to reply to this topic.