在 powershell 中限制启动进程的数量 运行
Limit number of Start-Process running in powershell
我试图限制来自 Powershell 的 Start-Process
运行 的数量,但我似乎无法让它工作。
我试着遵循这个过程:https://exchange12rocks.org/2015/05/24/how-to-limit-a-number-of-powershell-jobs-running-simultaneously/ and Run N parallel jobs in powershell
但这些是针对作业而非流程的,我想从 Start-Process
中删除 -Wait
我对脚本的担心是,如果文件夹中有 1000 个音频文件,那么 FFMpeg 会使系统崩溃。
# get the folder for conversion
function mbAudioConvert {
[Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms") | Out-Null
[System.Windows.Forms.Application]::EnableVisualStyles()
$fileBrowser = New-Object System.Windows.Forms.FolderBrowserDialog
$fileBrowser.SelectedPath = "B:\"
$fileBrowser.ShowNewFolderButton = $false
$fileBrowser.Description = "Select the folder with the audio which you wish to convert to Avid DNxHD 120 25P 48kHz"
$mbLoop = $true
$mbCount = 0001
$mbMaxJob = 4
while( $mbLoop ) {
if( $fileBrowser.ShowDialog() -eq "OK" ) {
$mbLoop = $false
$mbImage = ( Get-Item -Path "C:\Users\user\Desktop\lib\AudioOnly.jpg" )
$mbff32 = ( Get-Item -Path "C:\Users\user\Desktop\lib\ffmpeg32.exe" )
$mbff64 = ( Get-Item -Path "C:\Users\user\Desktop\lib\ffmpeg64.exe" )
$mbFolder = $fileBrowser.SelectedPath
$mbItemInc = ( ls $mbFolder\* -Include *.mp3, *.MP3, *.wav*, *.WAV*, *.ogg, *.OGG, *.wma, *.WMA, *.flac, *.FLAC, *.m4a, *.M4a )
$mbProgress = ( Get-ChildItem -Path $mbItemInc )
$mbHasRaw = ( $mbFolder + "\RAW" )
if( !( Test-Path -Path $mbHasRaw ) ) {
# force create a RAW folder if it does not exist
New-Item -ItemType Directory -Force -Path "$mbHasRaw"
}
foreach( $mbItem in $mbItemInc ) {
$mbCheck = $false
# output the progress
# Suggestion: You might want to consider updating this after starting the job and do the final update after running ex. Get-Job | Wait-Job to make the progress-bar stay until all processes are finished
#Write-Progress -Activity "Counting files for conversion" -status "Currently processing: $mbCount" -percentComplete ($mbCount / $mbItemInc.count*100)
# limit the run number
while ($mbCheck -eq $false) {
if( (Get-Job -State 'Running').count -lt $mbMaxJob) {
$mbScriptBlock = {
$mbItemName = $using:mbItem.BaseName
$mbNewItem = ( $using:mbFolder + "\RAW\" + $mbItemName + ".mov" )
$mbArgs = " -loop 1 -i $using:mbImage -i $using:mbItem -shortest -c:v dnxhd -b:v 120M -s 1920x1080 -pix_fmt yuv422p -r 25 -c:a pcm_s16le -ar 48k -af loudnorm=I=-12 $mbNewItem"
Start-Process -FilePath $using:mbff32 -ArgumentList $mbArgs -NoNewWindow -Wait
}
Start-Job -ScriptBlock $mbScriptBlock
#The job-thread doesn't know about $mbCount, better to increment it after starting the job
$mbCount++
$mbCheck = $true
}
}
}
} else {
$mbResponse = [System.Windows.Forms.MessageBox]::Show("You have exited out of the automation process!", "User has cancelled")
if( $mbResponse -eq "OK" ) {
return
}
}
}
$fileBrowser.SelectedPath
$fileBrowser.Dispose()
}
# call to function
mbAudioConvert
- 您编辑
$mbCheck
,但 while 循环正在测试 $Check
,这意味着 while-loop 将永远不会执行,因为 $Check -eq $false
是 $false
当 $Check
未定义
- 在作业外创建的变量 script-block 需要作为参数传递,或者您需要使用
using:
variable-scope 将它们传递进来(PowerShell 3.0 或更高版本)。将其添加到示例中未定义的 $mbItem
、$mbff32
、$mbImage
和 $mbFolder
。
$mbMaxJob
未定义。 get 运行 jobs-check 永远不会为真,也不会启动任何进程
$mbCount
未定义。进度条不起作用
echo "$mbCount. $mbNewItem"
不会 return 任何东西,除非你在某个时候使用 Receive-Job
从作业中获取输出
尝试:
#DemoValues
$mbItemInc = 1..10 | % { New-Item -ItemType File -Name "File$_.txt" }
$mbff32 = "something32"
$mbFolder = "c:\FooFolder"
$mbImage = "BarImage"
$mbMaxJob = 2
$mbCount = 0
foreach( $mbItem in $mbItemInc ) {
$mbCheck = $false
# output the progress
# Suggestion: You might want to consider updating this after starting the job and do the final update after running ex. Get-Job | Wait-Job to make the progress-bar stay until all processes are finished
Write-Progress -Activity "Counting files for conversion" -status "Currently processing: $mbCount" -percentComplete ($mbCount / $mbItemInc.count*100)
# limit the run number
while ($mbCheck -eq $false) {
if ((Get-Job -State 'Running').count -lt $mbMaxJob) {
$mbScriptBlock = {
Param($mbItem, $mbFolder, $mbImage, $mbff32)
#Filename without extension is already available in a FileInfo-object using the BaseName-property
$mbItemName = $mbItem.BaseName
$mbNewItem = ( $mbFolder + "\RAW\" + $mbItemName + ".mov" )
$mbArgs = "-loop 1 -i $mbImage -i $mbItem -shortest -c:v dnxhd -b:v 120M -s 1920x1080 -pix_fmt yuv422p -r 25 -c:a pcm_s16le -ar 48k -af loudnorm=I=-12 $mbNewItem"
Start-Process -FilePath $mbff32 -ArgumentList $mbArgs -NoNewWindow -Wait
}
Start-Job -ScriptBlock $mbScriptBlock -ArgumentList $mbItem, $mbFolder, $mbImage, $mbff32
#The job-thread doesn't know about $mbCount, better to increment it after starting the job
$mbCount++
$mbCheck = $true
}
}
}
我向您推荐我的解决方案:
cls
$FormatNameJob="FFMPEG"
$maxConcurrentJobs = 100
$DirWithFile="C:\temp"
$DestFolder="C:\temp2"
$TraitmentDir="C:\temp\traitment"
$PathFFMpeg="C:\Temp\ffmpeg\ffmpeg\bin\ffmpeg.exe"
$HistoFolder="C:\temp\histo"
#create dir if dont exists
New-Item -ItemType Directory -Path $TraitmentDir -Force | Out-Null
New-Item -ItemType Directory -Path $DestFolder -Force | Out-Null
New-Item -ItemType Directory -Path $HistoFolder -Force | Out-Null
while ($true)
{
"Loop File"
$ListeFile=Get-ChildItem $DirWithFile -file -Filter "*.avi"
if ($ListeFile.count -eq 0 )
{
Start-Sleep -Seconds 1
continue
}
#loop file to trait
$ListeFile | %{
while ((get-job -State Running | where Name -eq $FormatNameJob ).Count -ge $maxConcurrentJobs)
{
Start-Sleep -Seconds 1
get-job -State Completed | where Name -eq $FormatNameJob | Remove-Job
}
"traitment file : {0}" -f $_.Name
#build newname and move item into traitment dir
$NewfileName="{0:yyyyMMddHHmmssfffff}_{1}" -f (get-date), $_.Name
$ItemTraitment=[io.path]::Combine($TraitmentDir, $NewfileName)
$mbNewItem ="{0}.mov" -f [io.path]::Combine($DestFolder, $_.BaseName)
Move-item $_.FullName -Destination $ItemTraitment
#build arguments and command
$mbArgs = " -loop 1 -i $ItemTraitment -shortest -c:v dnxhd -b:v 120M -s 1920x1080 -pix_fmt yuv422p -r 25 -c:a pcm_s16le -ar 48k -af loudnorm=I=-12 $mbNewItem"
$ScriptBlock=[scriptblock]::Create("Start-Process $PathFFMpeg -ArgumentList $mbArgs -Wait")
#add job
Start-Job -ScriptBlock $ScriptBlock -Name $FormatNameJob
}
}
我试图限制来自 Powershell 的 Start-Process
运行 的数量,但我似乎无法让它工作。
我试着遵循这个过程:https://exchange12rocks.org/2015/05/24/how-to-limit-a-number-of-powershell-jobs-running-simultaneously/ and Run N parallel jobs in powershell
但这些是针对作业而非流程的,我想从 Start-Process
-Wait
我对脚本的担心是,如果文件夹中有 1000 个音频文件,那么 FFMpeg 会使系统崩溃。
# get the folder for conversion
function mbAudioConvert {
[Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms") | Out-Null
[System.Windows.Forms.Application]::EnableVisualStyles()
$fileBrowser = New-Object System.Windows.Forms.FolderBrowserDialog
$fileBrowser.SelectedPath = "B:\"
$fileBrowser.ShowNewFolderButton = $false
$fileBrowser.Description = "Select the folder with the audio which you wish to convert to Avid DNxHD 120 25P 48kHz"
$mbLoop = $true
$mbCount = 0001
$mbMaxJob = 4
while( $mbLoop ) {
if( $fileBrowser.ShowDialog() -eq "OK" ) {
$mbLoop = $false
$mbImage = ( Get-Item -Path "C:\Users\user\Desktop\lib\AudioOnly.jpg" )
$mbff32 = ( Get-Item -Path "C:\Users\user\Desktop\lib\ffmpeg32.exe" )
$mbff64 = ( Get-Item -Path "C:\Users\user\Desktop\lib\ffmpeg64.exe" )
$mbFolder = $fileBrowser.SelectedPath
$mbItemInc = ( ls $mbFolder\* -Include *.mp3, *.MP3, *.wav*, *.WAV*, *.ogg, *.OGG, *.wma, *.WMA, *.flac, *.FLAC, *.m4a, *.M4a )
$mbProgress = ( Get-ChildItem -Path $mbItemInc )
$mbHasRaw = ( $mbFolder + "\RAW" )
if( !( Test-Path -Path $mbHasRaw ) ) {
# force create a RAW folder if it does not exist
New-Item -ItemType Directory -Force -Path "$mbHasRaw"
}
foreach( $mbItem in $mbItemInc ) {
$mbCheck = $false
# output the progress
# Suggestion: You might want to consider updating this after starting the job and do the final update after running ex. Get-Job | Wait-Job to make the progress-bar stay until all processes are finished
#Write-Progress -Activity "Counting files for conversion" -status "Currently processing: $mbCount" -percentComplete ($mbCount / $mbItemInc.count*100)
# limit the run number
while ($mbCheck -eq $false) {
if( (Get-Job -State 'Running').count -lt $mbMaxJob) {
$mbScriptBlock = {
$mbItemName = $using:mbItem.BaseName
$mbNewItem = ( $using:mbFolder + "\RAW\" + $mbItemName + ".mov" )
$mbArgs = " -loop 1 -i $using:mbImage -i $using:mbItem -shortest -c:v dnxhd -b:v 120M -s 1920x1080 -pix_fmt yuv422p -r 25 -c:a pcm_s16le -ar 48k -af loudnorm=I=-12 $mbNewItem"
Start-Process -FilePath $using:mbff32 -ArgumentList $mbArgs -NoNewWindow -Wait
}
Start-Job -ScriptBlock $mbScriptBlock
#The job-thread doesn't know about $mbCount, better to increment it after starting the job
$mbCount++
$mbCheck = $true
}
}
}
} else {
$mbResponse = [System.Windows.Forms.MessageBox]::Show("You have exited out of the automation process!", "User has cancelled")
if( $mbResponse -eq "OK" ) {
return
}
}
}
$fileBrowser.SelectedPath
$fileBrowser.Dispose()
}
# call to function
mbAudioConvert
- 您编辑
$mbCheck
,但 while 循环正在测试$Check
,这意味着 while-loop 将永远不会执行,因为$Check -eq $false
是$false
当$Check
未定义 - 在作业外创建的变量 script-block 需要作为参数传递,或者您需要使用
using:
variable-scope 将它们传递进来(PowerShell 3.0 或更高版本)。将其添加到示例中未定义的$mbItem
、$mbff32
、$mbImage
和$mbFolder
。 $mbMaxJob
未定义。 get 运行 jobs-check 永远不会为真,也不会启动任何进程$mbCount
未定义。进度条不起作用echo "$mbCount. $mbNewItem"
不会 return 任何东西,除非你在某个时候使用Receive-Job
从作业中获取输出
尝试:
#DemoValues
$mbItemInc = 1..10 | % { New-Item -ItemType File -Name "File$_.txt" }
$mbff32 = "something32"
$mbFolder = "c:\FooFolder"
$mbImage = "BarImage"
$mbMaxJob = 2
$mbCount = 0
foreach( $mbItem in $mbItemInc ) {
$mbCheck = $false
# output the progress
# Suggestion: You might want to consider updating this after starting the job and do the final update after running ex. Get-Job | Wait-Job to make the progress-bar stay until all processes are finished
Write-Progress -Activity "Counting files for conversion" -status "Currently processing: $mbCount" -percentComplete ($mbCount / $mbItemInc.count*100)
# limit the run number
while ($mbCheck -eq $false) {
if ((Get-Job -State 'Running').count -lt $mbMaxJob) {
$mbScriptBlock = {
Param($mbItem, $mbFolder, $mbImage, $mbff32)
#Filename without extension is already available in a FileInfo-object using the BaseName-property
$mbItemName = $mbItem.BaseName
$mbNewItem = ( $mbFolder + "\RAW\" + $mbItemName + ".mov" )
$mbArgs = "-loop 1 -i $mbImage -i $mbItem -shortest -c:v dnxhd -b:v 120M -s 1920x1080 -pix_fmt yuv422p -r 25 -c:a pcm_s16le -ar 48k -af loudnorm=I=-12 $mbNewItem"
Start-Process -FilePath $mbff32 -ArgumentList $mbArgs -NoNewWindow -Wait
}
Start-Job -ScriptBlock $mbScriptBlock -ArgumentList $mbItem, $mbFolder, $mbImage, $mbff32
#The job-thread doesn't know about $mbCount, better to increment it after starting the job
$mbCount++
$mbCheck = $true
}
}
}
我向您推荐我的解决方案:
cls
$FormatNameJob="FFMPEG"
$maxConcurrentJobs = 100
$DirWithFile="C:\temp"
$DestFolder="C:\temp2"
$TraitmentDir="C:\temp\traitment"
$PathFFMpeg="C:\Temp\ffmpeg\ffmpeg\bin\ffmpeg.exe"
$HistoFolder="C:\temp\histo"
#create dir if dont exists
New-Item -ItemType Directory -Path $TraitmentDir -Force | Out-Null
New-Item -ItemType Directory -Path $DestFolder -Force | Out-Null
New-Item -ItemType Directory -Path $HistoFolder -Force | Out-Null
while ($true)
{
"Loop File"
$ListeFile=Get-ChildItem $DirWithFile -file -Filter "*.avi"
if ($ListeFile.count -eq 0 )
{
Start-Sleep -Seconds 1
continue
}
#loop file to trait
$ListeFile | %{
while ((get-job -State Running | where Name -eq $FormatNameJob ).Count -ge $maxConcurrentJobs)
{
Start-Sleep -Seconds 1
get-job -State Completed | where Name -eq $FormatNameJob | Remove-Job
}
"traitment file : {0}" -f $_.Name
#build newname and move item into traitment dir
$NewfileName="{0:yyyyMMddHHmmssfffff}_{1}" -f (get-date), $_.Name
$ItemTraitment=[io.path]::Combine($TraitmentDir, $NewfileName)
$mbNewItem ="{0}.mov" -f [io.path]::Combine($DestFolder, $_.BaseName)
Move-item $_.FullName -Destination $ItemTraitment
#build arguments and command
$mbArgs = " -loop 1 -i $ItemTraitment -shortest -c:v dnxhd -b:v 120M -s 1920x1080 -pix_fmt yuv422p -r 25 -c:a pcm_s16le -ar 48k -af loudnorm=I=-12 $mbNewItem"
$ScriptBlock=[scriptblock]::Create("Start-Process $PathFFMpeg -ArgumentList $mbArgs -Wait")
#add job
Start-Job -ScriptBlock $ScriptBlock -Name $FormatNameJob
}
}