PowerShell 作业,写入文件
PowerShell Jobs, writing to a file
在将 Start-Job 脚本块输出到文件时遇到一些问题。以下三行代码没有任何问题:
$about_name = "C:[=10=]\ps_about_name.txt"
$about = get-help about_* | select Name,Synopsis
if (-not (Test-
Path $about_name)) { ($about | select Name | sort Name | Out-String).replace("[Aa]bout_", "") > $about_name }
文件创建于C:\0\
但是我需要做很多这样的收集,所以我自然而然地考虑将它们作为单独的工作并行堆叠。我按照在线示例进行操作,因此将上面的最后一行作为 Start-Job 调用的脚本块:
Start-Job { if (-not (Test-Path $about_name)) { { ($about | select Name | sort Name | Out-String).replace("[Aa]bout_", "") > $about_name } }
作业已创建,进入状态 运行,然后进入状态已完成,但未创建任何文件。没有 Start-Job,一切正常,有了 Start-Job,什么都没有……我已经尝试了很多变体,但无法创建文件。有人可以告诉我在这方面做错了什么吗?
您必须将参数发送到作业。
这不起作用:
$file = "C:\temp\_mytest.txt"
start-job {"_" | out-file $file}
同时这样做:
$file = "C:\temp\_mytest.txt"
start-job -ArgumentList $file -scriptblock {
Param($file)
"_" | out-file $file
}
IMO,使用 $using
作用域修饰符是解决此问题的最简单方法。
$about_name = "C:[=10=]\ps_about_name.txt"
$about = get-help about_* | select Name,Synopsis
$sb = { if (-not (Test-Path $using:about_name)) {
$using:about.Name -replace '^about_' | Sort-Object > $using:about_name
}
}
Start-Job -Scriptblock $sb
解释:
$using
允许您在远程命令中访问局部变量。这在 运行 Start-Job
和 Invoke-Command
时特别有用。语法是 $using:localvariable
.
这个特殊问题是一个可变范围问题。 Start-Job creates a background job with its own scope. When using -Scriptblock
parameter, you are working within that scope. It does not know about variables defined in your current scope/session. Therefore, you must use a technique that will define the variable within the scope, pass in the variable's value, or access the local scope from the script block. You can read more about scopes at About_Scopes.
顺便说一句,.NET .Replace()
方法不支持字符集 []
。您需要切换到 -replace
才能使用它们。我更新了代码以使用不区分大小写的 -replace
执行替换。
使用一种将值传递到作业的脚本块的技术。通过在脚本块中定义参数,您可以使用 -ArgumentList
.
将值传递到该参数
另一种选择是只在 Start-Job
脚本块中定义变量。
$sb = { $about_name = "C:[=11=]\ps_about_name.txt"
$about = get-help about_* | select Name,Synopsis
if (-not (Test-Path $about_name)) {
$about.Name -replace '^about_' | Sort-Object > $about_name
}
}
Start-Job -Scriptblock $sb
在将 Start-Job 脚本块输出到文件时遇到一些问题。以下三行代码没有任何问题:
$about_name = "C:[=10=]\ps_about_name.txt"
$about = get-help about_* | select Name,Synopsis
if (-not (Test-
Path $about_name)) { ($about | select Name | sort Name | Out-String).replace("[Aa]bout_", "") > $about_name }
文件创建于C:\0\
但是我需要做很多这样的收集,所以我自然而然地考虑将它们作为单独的工作并行堆叠。我按照在线示例进行操作,因此将上面的最后一行作为 Start-Job 调用的脚本块:
Start-Job { if (-not (Test-Path $about_name)) { { ($about | select Name | sort Name | Out-String).replace("[Aa]bout_", "") > $about_name } }
作业已创建,进入状态 运行,然后进入状态已完成,但未创建任何文件。没有 Start-Job,一切正常,有了 Start-Job,什么都没有……我已经尝试了很多变体,但无法创建文件。有人可以告诉我在这方面做错了什么吗?
您必须将参数发送到作业。 这不起作用:
$file = "C:\temp\_mytest.txt"
start-job {"_" | out-file $file}
同时这样做:
$file = "C:\temp\_mytest.txt"
start-job -ArgumentList $file -scriptblock {
Param($file)
"_" | out-file $file
}
IMO,使用 $using
作用域修饰符是解决此问题的最简单方法。
$about_name = "C:[=10=]\ps_about_name.txt"
$about = get-help about_* | select Name,Synopsis
$sb = { if (-not (Test-Path $using:about_name)) {
$using:about.Name -replace '^about_' | Sort-Object > $using:about_name
}
}
Start-Job -Scriptblock $sb
解释:
$using
允许您在远程命令中访问局部变量。这在 运行 Start-Job
和 Invoke-Command
时特别有用。语法是 $using:localvariable
.
这个特殊问题是一个可变范围问题。 Start-Job creates a background job with its own scope. When using -Scriptblock
parameter, you are working within that scope. It does not know about variables defined in your current scope/session. Therefore, you must use a technique that will define the variable within the scope, pass in the variable's value, or access the local scope from the script block. You can read more about scopes at About_Scopes.
顺便说一句,.NET .Replace()
方法不支持字符集 []
。您需要切换到 -replace
才能使用它们。我更新了代码以使用不区分大小写的 -replace
执行替换。
-ArgumentList
.
另一种选择是只在 Start-Job
脚本块中定义变量。
$sb = { $about_name = "C:[=11=]\ps_about_name.txt"
$about = get-help about_* | select Name,Synopsis
if (-not (Test-Path $about_name)) {
$about.Name -replace '^about_' | Sort-Object > $about_name
}
}
Start-Job -Scriptblock $sb