1

I'm fairly new to powershell. The below is my attempt to return records of software on a list of systems via invoke-command. It does work. However, it seems like all results are stored in memory and then exported to the CSV all at once. Instead, I'd like to offload the results in batches or as they're returned. Whichever is the simplest method. That way, I can run similar similar CMDs from our servers, without it bogging down my server that's running the scripts, whose memory is at 99% load at the moment, and then the CPU jumps to 99% after the script completes to offload the results.

$IC_ScriptBlock = {
    Get-itemproperty -Path Registry::HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\currentversion\Uninstall* |
        Select Publisher, DisplayName, DisplayVersion, installDate
        }
$IC_Params = @{
    ThrottleLimit = 100
    ScriptBlock = $IC_ScriptBlock
    ComputerName = (Get-Content "C:\Users\JT\Desktop\Scripts\laptops.txt")
    }
Invoke-Command @IC_Params |
    Export-csv -NoTypeInformation -Path "C:\Users\JT\Desktop\Scripts\laptops.csv" -Delimiter ";"
pfx
  • 20,323
  • 43
  • 37
  • 57
J T
  • 59
  • 2
  • 6
  • what happens if you break the pipeline? put the output of the I-C into a $Var and the send that to the CSV in a separate step? i ask because the pipeline is known to take a bit more resources than one expects. – Lee_Dailey Mar 09 '19 at 21:11
  • Didn't work, without the Pipe it just shows the results to my CMDlet and doesn't export. I think it's because it's running as a scriptblock. I may have to write something else. – J T Mar 09 '19 at 23:37
  • well, you WOULD need to assign the `Invoke-Command` to a $Var. [*grin*] then use that to pipe to `Export-CSV`. ///// it seems rather strange that even a few hundred systems would use up that much RAM, tho. [*frown*] ///// what are you doing about non-responding systems? – Lee_Dailey Mar 09 '19 at 23:41
  • The only systems that don't respond are probably due to DNS errors. Actually, I work for a rather large enterprise, workstations alone are in the 10's of thousands. The inovke-command does have a variable $Computer, which is a txt file with thousands of workstations. Right now, i'm looking to maybe try and run them in batches, with -readcount 20. looks like it's working... – J T Mar 10 '19 at 01:10
  • ah! thank you for the added info ... and the readcount method is likely going to help quite a bit. good luck! [*grin*] – Lee_Dailey Mar 10 '19 at 01:13

1 Answers1

1

Looks like the below is what I needed.

 $Computers = Get-Content "C:\Desktop\workstations.txt" -ReadCount 20
    FOREACH ($Computer in $Computers) {
    Invoke-Command -ComputerName $Computer -ScriptBlock {
    Get-itemproperty -Path Registry::HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\currentversion\Uninstall\* | 
    Select @{Name="HostName";Expression={$Computer}}, Publisher, DisplayName, DisplayVersion, installDate} |
    Export-csv -NoTypeInformation -Path "C:\Desktop\results.csv" -Delimiter ";" -Append
    } 
    {
    Start-Sleep 1
    }
J T
  • 59
  • 2
  • 6
  • I think `-ThrottleLimit 20` should give you the same, without manual batching via `Get-Content -ReadCount 20` + `foreach` - have you tried that? – mklement0 Mar 10 '19 at 02:42
  • Also, if I interpret `-ThrottleLimit` correctly (I cannot personally verify the behavior), it would give you a rolling window of 20 connections at time, which should be more efficient than waiting for all 20 machines per batch to finish before starting the next batch. I don't know how this affects the output behavior, however. – mklement0 Mar 10 '19 at 03:07