我正在嘗試獲取 windows 系統目錄 (C:\Windows\System32) 中的 dll 和 exe 檔案名。
該路徑中的檔案太多,所以我嘗試使用多執行緒。
但是,當比較(在“IF”陳述句中)Addscript添加的ScriptBlock中的擴展名時,只會出現“False”結果,因此無法將檔案名添加到串列中。
if ($extensionList -contains $tmpExtension.ToString())
也許條件陳述句錯誤或 ScriptBlock 錯誤?當不使用多執行緒時,條件陳述句正常作業。
完整代碼(Powershell 5.1):
$extensionList = @(".DLL",".EXE")
$systemDir = "C:\Windows\System32\"
$threadNumber = 4 #threads
$tempList = @()
$ScriptBlock = {
Param ($tmpFilePath)
$tmpExtension = [IO.Path]::GetExtension($tmpFilePath)
if ($extensionList -contains $tmpExtension.ToString()) {
Return $tmpFilePath
}
Return $null
}
$RunspacePool = [RunspaceFactory]::CreateRunspacePool(1, $threadNumber)
$RunspacePool.Open()
$Jobs = @()
$tmpfileNameList = (Get-ChildItem -Path $systemDir -File) | select-object Name
foreach($tmpfileName in $tmpfileNameList) {
$tmpFilePath = $systemDir $tmpfileName.Name
$Job = [powershell]::Create().AddScript($ScriptBlock).AddArgument($tmpFilePath)
$Job.RunspacePool = $RunspacePool
$Jobs = New-Object PSObject -Property @{
Pipe = $Job
Result = $Job.BeginInvoke()
}
}
while ($Jobs.IsCompleted -contains $false) {Start-Sleep -Milliseconds 100}
$Results = @()
ForEach ($Job in $Jobs){
if ($Job.Pipe.EndInvoke($Job.Result) -ne $null) {
$tempList = $Job.Pipe.EndInvoke($Job.Result)
}
}
foreach($tmp in $tempList) {
Write-Host $tmp
}
uj5u.com熱心網友回復:
主要問題是您的powershell實體不知道是什么$extensionList,因為它從未作為引數傳遞,因此它總是評估:
$null -contains [IO.Path]::GetExtension($tmpFilePath)
如果您的意圖是回傳FullName其擴展名所在的檔案,.dll或者.exe您scriptblock應該是這樣的:
$ScriptBlock = {
Param ($tmpFilePath, $extensionList)
if ($extensionList -contains [IO.Path]::GetExtension($tmpFilePath))
{
$tmpFilePath
}
}
而foreach回圈是這樣的:
$tmpfileNameList = (Get-ChildItem -Path $systemDir -File).FullName
$params = @{
extensionList = $extensionList
}
$jobs = foreach($path in $tmpfileNameList)
{
$params.tmpFilePath = $path
$Job = [powershell]::Create().AddScript($ScriptBlock).AddParameters($params)
$Job.RunspacePool = $RunspacePool
[pscustomobject]@{
Pipe = $Job
Result = $Job.BeginInvoke()
}
}
詳情請參閱PowerShell.AddParameters Method。
那么這一行是錯誤的:
while ($Jobs.IsCompleted -contains $false) {
Start-Sleep -Milliseconds 100
}
也應該改變:
while ($Jobs.Result.IsCompleted -contains $false) {
Start-Sleep -Milliseconds 100
}
最后,您可以獲得運行空間的結果,例如:
$results = $jobs.ForEach({ $_.Pipe.EndInvoke($_.Result) })
PS /> $results
除了上面提到的內容之外,還需要改進邏輯以使腳本真正高效。
不是將一個路徑傳遞給每個powershell實體,您應該將array路徑 ( $tmpfileNameList) 拆分為多個塊,并為每個實體提供一個要處理的塊。
你可以使用這樣的東西來分割你的array:
$groupSize = [math]::Ceiling($tmpfileNameList.Count / $threadNumber)
$counter = [pscustomobject]@{ Value = 0 }
$groups = $tmpfileNameList | Group-Object -Property {
[math]::Floor($counter.Value / $groupSize)
}
在這種情況下,由于您使用的是4執行緒,因此$groups將包含 4 個組。如果您想將此技術應用于您的代碼,您可以從此鏈接復制邏輯。
轉載請註明出處,本文鏈接:https://www.uj5u.com/qukuanlian/368908.html
標籤:电源外壳
上一篇:使用PowerShell腳本根據txt檔案中的檔案/檔案夾結構移動一個檔案夾中的所有檔案
下一篇:Powershell輸出大括號
