PowerShell 技能连载 - Real-Time Processing for Language Structures
In the previous tip we looked at queues and how they can search the entire file system:
# create a new queue
$dirs = [System.Collections.Queue]::new()
# add an initial path to the queue
# any folder path in the queue will later be processed
$dirs.Enqueue('c:\windows')
# process all elements on the queue until all are taken
While ($current = $dirs.Dequeue())
{
# find subfolders of current folder, and if present,
# add them all to the queue
try
{
foreach ($_ in [IO.Directory]::GetDirectories($current))
{
$dirs.Enqueue($_)
}
} catch {}
try
{
# find all files in the folder currently processed
[IO.Directory]::GetFiles($current, "*.exe")
[IO.Directory]::GetFiles($current, "*.ps1")
} catch { }
}
How would you process the data created by the loop though, i.e. to display it in a grid view window? You cannot pipe it in real-time, so this fails:
$dirs = [System.Collections.Queue]::new()
$dirs.Enqueue('c:\windows')
While ($current = $dirs.Dequeue())
{
try
{
foreach ($_ in [IO.Directory]::GetDirectories($current))
{
$dirs.Enqueue($_)
}
} catch {}
try
{
[IO.Directory]::GetFiles($current, "*.exe")
[IO.Directory]::GetFiles($current, "*.ps1")
} catch { }
# this fails
} | Out-GridView
You can save the results produced by do-while to a variable. That works but takes forever because you’d have to wait for the loop to complete until you can do something with the variable:
$dirs = [System.Collections.Queue]::new()
$dirs.Enqueue('c:\windows')
# save results to variable...
$all = while ($current = $dirs.Dequeue())
{
try
{
foreach ($_ in [IO.Directory]::GetDirectories($current))
{
$dirs.Enqueue($_)
}
} catch {}
try
{
[IO.Directory]::GetFiles($current, "*.exe")
[IO.Directory]::GetFiles($current, "*.ps1")
} catch { }
}
# then process or output
$all | Out-GridView
The same limitation applies when you use $() or other constructs. To process the results emitted by do-while in true real-time, use a script block instead:
$dirs = [System.Collections.Queue]::new()
$dirs.Enqueue('c:\windows')
# run the code in a script block
& { while ($current = $dirs.Dequeue())
{
try
{
foreach ($_ in [IO.Directory]::GetDirectories($current))
{
$dirs.Enqueue($_)
}
} catch {}
try
{
[IO.Directory]::GetFiles($current, "*.exe")
[IO.Directory]::GetFiles($current, "*.ps1")
} catch { }
}
} | Out-GridView
With this approach, results start to show in the grid view window almost momentarily, and you don’t have to wait for the loop to complete.
psconf.eu – PowerShell Conference EU 2019 – June 4-7, Hannover Germany – visit www.psconf.eu There aren’t too many trainings around for experienced PowerShell scripters where you really still learn something new. But there’s one place you don’t want to miss: PowerShell Conference EU - with 40 renown international speakers including PowerShell team members and MVPs, plus 350 professional and creative PowerShell scripters. Registration is open at www.psconf.eu, and the full 3-track 4-days agenda becomes available soon. Once a year it’s just a smart move to come together, update know-how, learn about security and mitigations, and bring home fresh ideas and authoritative guidance. We’d sure love to see and hear from you!