Answered by:
Help - Speed up script - invoke-command checking drive size against 200 devices

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
- Edited by PRASOON KARUNAN V Saturday, November 25, 2017 5:07 PM
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