gpt4 book ai didi

powershell - 如何加快PowerShell foreach循环

转载 作者:行者123 更新时间:2023-12-03 01:28:57 26 4
gpt4 key购买 nike

我有一个PowerShell脚本,可以连接到数据库并提取用户数据列表。我获取这些数据并创建一个foreach循环以运行该数据的脚本。

这是可行的,但速度很慢,因为结果可能有1000多个条目,并且必须先完成Script.batUser A才能启动User B。一个用户的Script.bat独立于另一个用户,每个用户大约需要30秒。

有什么办法可以加快速度吗?我一直在使用-ParallelForEach-Objectworkflow,但是我无法使用它,可能是因为我是PS中的菜鸟。

foreach ($row in $Dataset.tables[0].rows)
{
$UserID=$row.value
$DeviceID=$row.value1
$EmailAddress=$row.email_address

cmd.exe /c "`"$PSScriptRoot`"\bin\Script.bat -c `" -Switch $UserID`" >> `"$PSScriptRoot`"\${FileName3}_REST_${DateTime}.txt 2> nul";
}

最佳答案

您自己说过,瓶颈在于脚本中的批处理文件,而不是循环本身。 foreach (而不是 ForEach-Object )已经是PowerShell中更快的foreach循环机制。 调查您的批处理文件,以找出为什么需要30秒才能完成,并在可能的情况下对其进行优化。

使用工作

Note: Start-Job will run the job under another process. If you have PowerShell Core you can make use of the Start-ThreadJob cmdlet in lieu of Start-Job. This will start your job as part of another thread of the same process instead of starting another process.



如果您无法优化批处理脚本或无法优化它来满足需要,那么可以考虑使用 Start-Job 启动该作业以异步执行,然后使用 Receive-Job 检查结果并从中获取任何输出。例如:
# Master list of jobs you need to check the result of later
$jobs = New-Object System.Collections.Generic.List[System.Management.Automation.Job]

# Run your script for each row
foreach ($row in $Dataset.tables[0].rows)
{
$UserID=$row.value
$DeviceID=$row.value1
$EmailAddress=$row.email_address

# Use Start-Job here to kick off the script and store the job information
# for later retrieval.
# The $using: scope modifier allows you to make use of variables that were
# defined in the session calling Start-Job
$job = Start-Job -ScriptBlock { cmd.exe /c "`"${using:PSScriptRoot}`"\bin\Script.bat -c `" -Switch ${using:UserID}`" >> `"${using:PSScriptRoot}`"\${using:FileName3}_REST_${DateTime}.txt 2> nul"; }

# Add the execution to the $jobs list to check the result of later
# Casting to void here prevents the Add method from returning the object
# we've added.
[void]$jobs.Add($job)
}

# Wait for the jobs to be done
Write-Host 'Waiting for all jobs to complete...'
while( $jobs | Where-Object { $_.State -eq 'Running' } ){
Start-Sleep -s 10
}

# Retrieve the output of the jobs
foreach( $j in $jobs ) {
Receive-Job $j
}

Note: Since you have ~1000 times you need to execute this script, you may want to consider writing your logic to only run a certain number of jobs at a time. My example above starts all necessary jobs without regarding the number that may execute at once.



有关作业和可以在运行/已完成的作业上检查的属性的更多信息,请查看以下链接:
  • About Jobs
  • Job Class
  • Using Scope *

  • * The documentation states that the using scope can only be declared when working with remote sessions, but this seems to work fine with Start-Job even if the job is local.

    关于powershell - 如何加快PowerShell foreach循环,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60007976/

    26 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com