locked
Help - Speed up script - invoke-command checking drive size against 200 devices RRS feed

  • Question

  • Hello,

    I am needing some help with speeding up this script and an overall check on the workflow...to see if I am running this in the best way.  The script is using the invoke-command against 200 machines to check on the D Drive size.  I was tasked with extending the drive with diskpart and now I am running this script to validate the drives are indeed extended.

    I would like some input

    • How to speed up the script.
    • Output results into a good check and bad check results file

    Thank you for your help.

    $servers = Get-Content -Path C:\Temp\All_VDI_FQDN_2.txt
    ForEach ($server in $servers) 
    {
      if (Test-Connection -ComputerName $server -Count 1) #-Quiet) 
      {
        Invoke-Command -ComputerName $server  -ScriptBlock {
          Get-PSDrive|
          Where-Object -FilterScript {
            $_.Name -eq 'D' -AND $_.Provider.Name -EQ 'FileSystem'
          }
        }-ThrottleLimit 50 |
        Sort-Object -Property PSComputerName|
        Format-Table -AutoSize | 
        
        Out-File -FilePath C:\Temp\GoodDriveCheck.txt -Append -Width 50
      }
      else 
      {
        Write-Warning -Message "Failed to ping $server"
        "Failed to ping $server" |Out-File -FilePath C:\Temp\DriveCheckFailedPing.txt -Append
      }
    }
    
    


    Thank you for your help and time, Robert Jaudon

    Saturday, November 25, 2017 3:09 PM

Answers

  • We can also use  "jobs" to speed this up dramatically.

    $job = Invoke-Command -ScriptBlock { Get-PSDrive D -PSProvider FileSystem } -AsJob -ComputerName $computers
    $job | Wait-Job
    $job.ChildJobs | Where-Object{ $_.State -eq 'Completed' } | receive-job | Sort-Object PsComputerName
    $job.ChildJobs | Where-Object{ $_.State -eq 'Failed' } | Select-Object location, state
    This will take only as long as running against one machine and may be easier that workflow for nonprogrammers.


    \_(ツ)_/

    JRV,

    Is this considered a 'workflow' or is this an example of PS jobs?  Just want to clarify as both jobs and workflows are areas I have not explored yet.

    Thank you for explaining,

    Rob


    Thank you for your help and time, Robert Jaudon

    • Marked as answer by rcjay272 Sunday, November 26, 2017 1:09 AM
    Saturday, November 25, 2017 10:04 PM

All replies

  • Ahh, an expensive code, Foreach here eats up your time and resources,

    -ComputerName accepts array of computers, no need to use a foreach here.

    Invoke-Command -ComputerName $servers -ScriptBlock {...}

    get the output to a variable, it will have the information of execution against all the servers.


    Regards kvprasoon


    Saturday, November 25, 2017 5:07 PM
  • Prasoon,

    Thank you for your reply.

    Could I run it like this...Would that be better?

    Invoke-Command -Computer (Get-Content C:\Temp\All_VDI_FQDN.txt) -ScriptBlock {...}



    Thank you for your help and time, Robert Jaudon

    Saturday, November 25, 2017 5:18 PM
  • The difference in speed will be trivial compared to the latency of doing this serially.  I suspect you speed improvement will be less than 1%.

    Use a workflow to speed this up.


    \_(ツ)_/

    Saturday, November 25, 2017 5:28 PM
  • This will run 50 times faster than any other method. All failed connections will be logged to "errors.txt

    $computers = Get-Content C:\Temp\All_VDI_FQDN.txt
    
    Invoke-AsWorkflow -CommandName Get-PsDrive -PSComputerName $computers -Parameter @{Name='D';PsProvider='FileSystem'} 2>errors.txt


    \_(ツ)_/


    • Edited by jrv Saturday, November 25, 2017 5:59 PM
    Saturday, November 25, 2017 5:59 PM
  • yes you can, but make sure there are no trailing spaces for each line in the text file,

    Regards kvprasoon

    Saturday, November 25, 2017 6:13 PM
  • This holds good if the user is using V3 and above

    Regards kvprasoon

    Saturday, November 25, 2017 6:15 PM
  • This holds good if the user is using V3 and above

    Regards kvprasoon

    No one should be using V2.  It is no longer supported on any platform that supports V3 or later.  For security reasons V2 should be removed from all systems.



    \_(ツ)_/

    Saturday, November 25, 2017 6:28 PM
  • We can also use  "jobs" to speed this up dramatically.

    $job = Invoke-Command -ScriptBlock { Get-PSDrive D -PSProvider FileSystem } -AsJob -ComputerName $computers
    $job | Wait-Job
    $job.ChildJobs | Where-Object{ $_.State -eq 'Completed' } | receive-job | Sort-Object PsComputerName
    $job.ChildJobs | Where-Object{ $_.State -eq 'Failed' } | Select-Object location, state
    This will take only as long as running against one machine and may be easier that workflow for nonprogrammers.


    \_(ツ)_/

    Saturday, November 25, 2017 6:31 PM
  • Ahh, an expensive code, Foreach here eats up your time and resources,

    -ComputerName accepts array of computers, no need to use a foreach here.

    Invoke-Command -ComputerName $servers -ScriptBlock {...}

    get the output to a variable, it will have the information of execution against all the servers.


    Regards kvprasoon


    An urban myth.  "foreach" in most cases does not cause performance issues.  You are misinterpreting an old hack that is only partially true and almost never an issue for other than very complex situations.

    Invoke-Command without "AsJob" still runs each server in order. 


    \_(ツ)_/


    • Edited by jrv Saturday, November 25, 2017 6:36 PM
    Saturday, November 25, 2017 6:34 PM
  • I should also note that running such a trivial command will never allow you to see the advantages of jobs because the overhead of any remote action will always be greater than most single commands.  More complex scripts will show the advantage and will eliminate continuous round trips to each remote system.


    \_(ツ)_/

    Saturday, November 25, 2017 6:49 PM
  • Thank you....I was just asking.

    As for the workflow option...I am not familiar with that...looking into it now.\

    Rob


    Thank you for your help and time, Robert Jaudon

    Saturday, November 25, 2017 9:52 PM
  • This will run 50 times faster than any other method. All failed connections will be logged to "errors.txt

    $computers = Get-Content C:\Temp\All_VDI_FQDN.txt
    
    Invoke-AsWorkflow -CommandName Get-PsDrive -PSComputerName $computers -Parameter @{Name='D';PsProvider='FileSystem'} 2>errors.txt


    \_(ツ)_/


    JRV,

    Thank you for the suggestion.  You're correct...this was much quicker.

    Rob.


    Thank you for your help and time, Robert Jaudon

    Saturday, November 25, 2017 10:00 PM
  • We can also use  "jobs" to speed this up dramatically.

    $job = Invoke-Command -ScriptBlock { Get-PSDrive D -PSProvider FileSystem } -AsJob -ComputerName $computers
    $job | Wait-Job
    $job.ChildJobs | Where-Object{ $_.State -eq 'Completed' } | receive-job | Sort-Object PsComputerName
    $job.ChildJobs | Where-Object{ $_.State -eq 'Failed' } | Select-Object location, state
    This will take only as long as running against one machine and may be easier that workflow for nonprogrammers.


    \_(ツ)_/

    JRV,

    Is this considered a 'workflow' or is this an example of PS jobs?  Just want to clarify as both jobs and workflows are areas I have not explored yet.

    Thank you for explaining,

    Rob


    Thank you for your help and time, Robert Jaudon

    • Marked as answer by rcjay272 Sunday, November 26, 2017 1:09 AM
    Saturday, November 25, 2017 10:04 PM
  • We can also use  "jobs" to speed this up dramatically.

    $job = Invoke-Command -ScriptBlock { Get-PSDrive D -PSProvider FileSystem } -AsJob -ComputerName $computers
    $job | Wait-Job
    $job.ChildJobs | Where-Object{ $_.State -eq 'Completed' } | receive-job | Sort-Object PsComputerName
    $job.ChildJobs | Where-Object{ $_.State -eq 'Failed' } | Select-Object location, state
    This will take only as long as running against one machine and may be easier that workflow for nonprogrammers.


    \_(ツ)_/

    JRV,

    Is this considered a 'workflow' or is this an example of PS jobs?  Just want to clarify as both jobs and workflows are areas I have not explored yet.

    Thank you for explaining,

    Rob


    Thank you for your help and time, Robert Jaudon

    This is a jobs solution which is a bit heavier than a workflow and uses more memory and processor bandwidth.  You need to become familiar with jobs and workflows and learn where they can be useful.

    Using Invoke or a workflow runs everything locally.  Invoke -AsJob runs the script remotely and can be many times faster because the work is distributed.

    A workflow can be designed to split the load using things like inline scripts and Wmi.


    \_(ツ)_/

    Saturday, November 25, 2017 10:50 PM
  • JRV,

    Thank you for your time and knowledge.  The examples are areas I will be looking into.

    Just so I'm clear using Invoke-asjob is useful for querying many remote machines, as in my script.

    Do I have that correct?

    Also...could you recommend some good resources for both Invoke-asjob and workflows?

    Thank you again....I truly appreciate your help.

    Rob


    Thank you for your help and time, Robert Jaudon

    Saturday, November 25, 2017 11:13 PM
  • It is "Invoke-Command -AsJob ..."

    help Invoke-command -online

    help about_workflow


    \_(ツ)_/

    Sunday, November 26, 2017 12:08 AM
  • Sunday, November 26, 2017 12:17 AM
  • Extra credit: http://www.powershellmagazine.com/2012/11/14/powershell-workflows/

    \_(ツ)_/

    Just checked out the link...Also going to purchase the the Toolmaking and scripting books.

    Much appreciated,

    Rob


    Thank you for your help and time, Robert Jaudon

    Sunday, November 26, 2017 1:10 AM