[英]“You cannot call a method on a null-valued expression.” when trying to receive Result of update Searcher running in Background Job
I need to List all updates on Windows that are not installed and write them to a file. 我需要列出Windows上所有未安装的更新,并将它们写入文件。 But if it takes too long there must be a timeout.
但是,如果花费的时间太长,则必须超时。
I tried to run a search with a Update Searcher Object as a Job and then continue either when it's completed or the timeout takes place. 我尝试使用更新搜索器对象作为作业来运行搜索,然后在完成搜索或发生超时时继续进行搜索。 Then I check if the job has been completed or not.
然后,我检查作业是否完成。 If it did I pass the job to
Receive-Job
to get its result and write it to the file. 如果这样做,我将作业传递给
Receive-Job
以获取其结果并将其写入文件。
$session = New-Object -ComObject "Microsoft.Update.Session"
$searcher = $session.CreateUpdateSearcher()
$j = Start-Job -ScriptBlock {
$searcher.Search("IsInstalled=0").Updates | Select-Object Type, Title, IsHidden
} | Wait-Job -Timeout 120
if ($j.State -eq 'Completed') {
Receive-Job $j -Keep | Out-File @out_options
} else {
echo "[TIMEOUT] Script took too long to fetch all missing updates." |
Out-File @out_options
}
@out_options
are defined, if you should wonder. 如果您想知道,则定义
@out_options
。
The only thing I receive is following error: 我收到的唯一是以下错误:
You cannot call a method on a null-valued expression.
+ CategoryInfo : InvalidOperation: (:) [], RuntimeException
+ FullyQualifiedErrorId : InvokeMethodOnNull
+ PSComputerName : localhost
By now I figured out that the error stems from calling Receive-Job
. 到现在为止,我发现错误是由调用
Receive-Job
。 It seems the job is completing before there is a result. 看来工作没有完成就没有结果。 How do I receive Result from my background job?
我如何从后台工作中收到结果?
You've run into a scope issue. 您遇到了范围问题。 The variable
$searcher
inside your scriptblock is in a different scope (and is thus a different variable) than the variable $searcher
in the script scope. 变量
$searcher
您的脚本块内处于不同范围(因此是不同的变量),比变量$searcher
在脚本范围。 Because it wasn't initialized properly the variable in the scriptblock is empty, thus causing the error you observed (you're trying to invoke Search()
on an empty value). 由于未正确初始化,因此脚本块中的变量为空,从而导致您观察到错误(您尝试对空值调用
Search()
)。
The usual fix for this would be either using the using
scope modifier 通常的解决方法是使用
using
范围修饰符
$j = Start-Job -ScriptBlock {
$
using:searcher.Search("IsInstalled=0").Updates | ...
} | ...
or passing the variable as an argument 或将变量作为参数传递
$j = Start-Job -ScriptBlock {
Param($s)
$s.Search("IsInstalled=0").Updates | ...
}
-ArgumentList $searcher | ...
However, in your case both approaches don't work, which to my knowledge is because of how COM objects are serialized/deserialized when being passed between different contexts. 但是,在您的情况下,这两种方法都不起作用,据我所知,这是因为在不同上下文之间传递COM对象时如何对其进行序列化/反序列化。
To avoid this pitfall create the Update session and searcher inside the scriptblock: 为了避免这种陷阱,请在脚本块内创建Update会话和搜索器:
$j = Start-Job -ScriptBlock {
$session = New-Object -ComObject 'Microsoft.Update.Session'
$searcher = $session.CreateUpdateSearcher()
$searcher.Search('IsInstalled=0').Updates | Select-Object Type, Title, IsHidden
} | Wait-Job -Timeout 120
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.