Make a Powershell function/task run in the background
Solution 1
In the new scope you create for the background job, your parameters defined for you WriteAllPaths function are not defined. Try this and you'll see they aren't:
Function writeAllPaths([string]$fromFolder,[string]$filter,[string]$printfile)
{
Start-Job { "$fromFolder, $filter, $printFile" }
}
$job = WriteAllPaths .\Downloads *.zip zips.txt
Wait-Job $job
Receive-Job $job
, ,
Try this instead:
Function writeAllPaths([string]$fromFolder, [string]$filter, [string]$printfile)
{
Start-Job {param($fromFolder,$filter,$printfile)
"$fromFolder, $filter, $printfile" } `
-ArgumentList $fromFolder,$filter,$printfile
}
$job = WriteAllPaths .\Downloads *.zip z.txt
Wait-Job $job
Receive-Job $job
.\Downloads, *.zip, z.txt
Now you see your output because we passed the parameters through to the scriptblock via -ArgumentList. What I would recommend is a function that can optionally use a background job. Just stick this function definition in your profile and you're set:
function WriteAllPaths([string]$FromFolder, [string]$Filter,
[string]$Printfile, [switch]$AsJob)
{
if (![IO.Path]::IsPathRooted($FromFolder)) {
$FromFolder = Join-Path $Pwd $FromFolder
}
if (![IO.Path]::IsPathRooted($PrintFile)) {
$PrintFile = Join-Path $Pwd $PrintFile
}
$sb = {
param($FromFolder, $Filter, $Printfile)
Get-ChildItem $FromFolder -r $filter | Select FullName > $PrintFile
}
if ($AsJob) {
Start-Job $sb -ArgumentList $FromFolder,$Filter,$PrintFile
}
else {
& $sb $FromFolder $Filter $PrintFile
}
}
Test the function (synchronously) like so:
$job = WriteAllPaths Downloads *.zip z.txt -AsJob
Wait-Job $job
Receive-Job $job
Note that I'm testing if the path is root and if not I'm prepending the current dir. I do this because the background job's starting dir is not always the same as where you executed Start-Job from.
Solution 2
Which version of powershell? In Powershell 2.0 I think you can use background jobs for this Start-Job.
Starts a Windows PowerShell background job.
KdgDev
Updated on June 04, 2022Comments
-
KdgDev almost 2 years
I have a function that lets me write the file-path of files to a text file, depending on your input. That sounds confusing, but I don't know of a better way to put it, so here's the function:
Function writeAllPaths([string]$fromFolder,[string]$filter,[string]$printfile) { Get-ChildItem -Path $fromFolder -Recurse $filter | Select-Object -Property FullName > $printfile }
First argument being the folder you start your search from.
Second argument, the filter. *.zip for instance, will list all zip files. Third argument, you have to provide where the text file will end up.Sample usage:
writeAllPaths c:\ *.zip c:\allZips.txt
The thing is, when I do this, Powershell won't accept commands until it's done. Which isn't very productive. Is there a way to have this run in the background when started. And preferably, give a little message when it's done. I could be opening any file that's being created in the middle of the process...
Also, I'm on Windows 7, so I'm guessing that I have Powershell 2.0
Yeah, I'm not sure about it :p
EDIT:
I used Start-Job, as suggested, as follows:
Function writeAllPaths([string]$fromFolder,[string]$filter,[string]$printfile) { Start-Job -ScriptBlock {Get-ChildItem -Path $fromFolder -Recurse $filter | Select-Object -Property FullName > $printfile} }
However, the file isn't created. The old function does create a file.
EDIT2: it would be preferable to have this function in my Powershell profile. This way, I can execute it whenever I want, instead of having to load in the specific ps1 file every time I boot Powershell.
More info on the Powershell profile can be found here You can summon your own profile by typing:
notepad $profile
-
KdgDev over 14 yearsI'm on Windows 7 Ultimate, so I'm guessing 2.0
-
cal meacham over 14 yearsWell then read up on PsJob, Start/Stop/Wait/Get/Remove/Receive-Job
-
KdgDev over 14 yearsAnd suppose I wanted to have this function in my Powershell Profile?
-
Keith Hill over 14 yearsI updated the post for this. Note the addition of the -AsJob param.
-
KdgDev over 14 yearsI should "Just stick this function definition in your profile and you're set". But what about the 3rd last-line. There is a reference to WriteAllPaths.ps1, which does not exist. Also, if I just paste this code into my profile, what will the effect of those last 3 lines be. They're not included in a function but exist directly in the profile. So everytime Powershell starts, it will try to execute them.
-
Keith Hill over 14 yearsJust paste the function. Those three lines just show how to execute in a synchronous manner. You wouldn't normally execute Wait-Job since you would want to do other work - rather than wait for the job to finish.