windows 使 Powershell 函数/任务在后台运行

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1691612/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-15 13:24:30  来源:igfitidea点击:

Make a Powershell function/task run in the background

windowspowershellbackground

提问by KdgDev

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.

第一个参数是您开始搜索的文件夹。
第二个参数,过滤器。*.zip 例如,将列出所有 zip 文件。第三个参数,您必须提供文本文件的最终位置。

Sample usage: writeAllPaths c:\ *.zip c:\allZips.txt

示例用法: 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...

问题是,当我这样做时,Powershell 在完成之前不会接受命令。这不是很有成效。有没有办法在启动时让它在后台运行。最好在完成后给一点信息。我可以打开在此过程中创建的任何文件...

Also, I'm on Windows 7, so I'm guessing that I have Powershell 2.0

另外,我在 Windows 7 上,所以我猜我有 Powershell 2.0

Yeah, I'm not sure about it :p

是的,我不确定:p

EDIT:

编辑:

I used Start-Job, as suggested, as follows:

我按照建议使用了 Start-Job,如下所示:

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.

EDIT2:最好在我的 Powershell 配置文件中使用此功能。这样,我可以随时执行它,而不必每次启动 Powershell 时都加载特定的 ps1 文件。

More info on the Powershell profile can be found hereYou can summon your own profile by typing: notepad $profile

可以在此处找到有关 Powershell 配置文件的更多信息 您可以通过键入以下内容来召唤您自己的配置文件:notepad $profile

回答by Keith Hill

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:

在您为后台作业创建的新作用域中,未定义为您的 WriteAllPaths 函数定义的参数。试试这个,你会发现它们不是:

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:

现在您可以看到您的输出,因为我们通过 -ArgumentList 将参数传递给脚本块。我推荐的是一个可以选择使用后台作业的功能。只需将此函数定义粘贴到您的配置文件中即可:

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.

请注意,我正在测试路径是否为根目录,如果不是,我将在当前目录之前添加。我这样做是因为后台作业的起始目录并不总是与您执行 Start-Job 的位置相同。

回答by jitter

Which version of powershell? In Powershell 2.0 I think you can use background jobs for this Start-Job.

哪个版本的powershell?在 Powershell 2.0 中,我认为您可以为此Start-Job使用后台作业。

Starts a Windows PowerShell background job.

启动 Windows PowerShell 后台作业。