当使用PSObject传递时,管道表达式中的计算属性在作业中返回null



我正试图将计算属性的哈希表传递到查询中,以便与Select-Object一起使用。它在控制台中运行时有效。我可以确认,该作业正在读取哈希表,因为它在结果中列出了选定的属性,但它们的所有值都为null。

注意:我知道我不需要对这些属性进行类型转换。我只是在展示我的问题。

如果我运行以下代码(这看起来很奇怪,但实际上有一个用例(,输出包含我选择的属性(来自$globalConfig.SystemState.Processors.SelectProperties(,但计算的属性的值为null,唯一返回正确值的属性是name:

$globalConfig = @{
PingAddress = '8.8.8.8';
SystemState = @{
Processors = @{
Namespace = 'rootcimv2';
ClassName = 'Win32_Processor';
SelectProperties = 'name', @{ n = 'CpuStatus'; e = { [int]$_.CpuStatus }}, @{ n = 'CurrentVoltage'; e = { [int]$_.CurrentVoltage }};
}
}
}
$job = Start-Job -Name Processors -ArgumentList $globalConfig.SystemState.Processors -ScriptBlock {
Try{
$Response = @{
State   = @();
Error   = $Null
}
$Response.State = Get-CimInstance -ClassName $Args[0].ClassName | Select-Object $Args[0].SelectProperties -ErrorAction Stop
}Catch{
$Response.Error = @{Id = 2; Message = "$($Args[0].Target) query failed: $($_.Exception.Message)"}
}
Return $Response
}
$job | Wait-Job
$job | Receive-Job | ConvertTo-Json -Depth 3
Id     Name            PSJobTypeName   State         HasMoreData     Location             Command
--     ----            -------------   -----         -----------     --------             -------
119    Processors      BackgroundJob   Completed     True            localhost            ...
{
"Error":  null,
"State":  {
"name":  "Intel(R) Core(TM) i7-4710MQ CPU @ 2.50GHz",
"CpuStatus":  null,
"CurrentVoltage":  null
}
}

然而,如果我运行相同的作业,但具有相同的硬编码计算属性(不是使用PSObject传递给Select Object(,它会按预期工作(输出中返回值112(:

$job = Start-Job -Name Processors -ArgumentList $globalConfig.SystemState.Processors -ScriptBlock {
Try{
$Response = @{
State   = @();
Error   = $Null
}
$Response.State = Get-CimInstance -ClassName $Args[0].ClassName | Select-Object Name, @{ n = 'CpuStatus'; e = { [int]$_.CpuStatus }},@{ n = 'CurrentVoltage'; e = { [int]$_.CurrentVoltage }}
}Catch{
$Response.Error = @{Id = 2; Message = "$($Args[0].Target) query failed: $($_.Exception.Message)"}
}
Return $Response
}
$job | Wait-Job
$job | Receive-Job | ConvertTo-Json -Depth 3
Id     Name            PSJobTypeName   State         HasMoreData     Location             Command
--     ----            -------------   -----         -----------     --------             -------
121    Processors      BackgroundJob   Completed     True            localhost            ...
{
"Error":  null,
"State":  {
"Name":  "Intel(R) Core(TM) i7-4710MQ CPU @ 2.50GHz",
"CpuStatus":  1,
"CurrentVoltage":  12
}
}

在作业内部时,如何将具有计算属性的对象内联传递给Select-Object

它是一个哈希表,而不是psobject。看起来你无法将脚本块传递到作业中。它们变成了琴弦。

$globalConfig = @{
PingAddress = '8.8.8.8'
SystemState = @{
Processors = @{
Namespace = 'rootcimv2'
ClassName = 'Win32_Processor'
SelectProperties = 'name', 
@{ n = 'CpuStatus'; e = { [int]$_.CpuStatus }},
@{ n = 'CurrentVoltage'; e = { [int]$_.CurrentVoltage }}
}
}
}
start-job -args $globalconfig.systemstate.processors {
$list = $args[0].selectproperties
$list[1].e.gettype()
$list[2].e.gettype()
} | receive-job -wait -auto

IsPublic IsSerial Name                                     BaseType
-------- -------- ----                                     --------
True     True     String                                   System.Object
True     True     String                                   System.Object

它适用于线程作业。线程obs不序列化它们的对象。在ps 5中,您可以从powershell库下载它。https://www.powershellgallery.com/packages/ThreadJob在ps 6&7,它自带。它不会产生新的过程,而且速度更快。(它没有"-args"别名。(

start-threadjob -argumentlist $globalconfig.systemstate.processors {
$list = $args[0].selectproperties
$list[1].e.gettype()
$list[2].e.gettype()
} | receive-job -wait -auto

IsPublic IsSerial Name                                     BaseType
-------- -------- ----                                     --------
True     True     ScriptBlock                              System.Object
True     True     ScriptBlock                              System.Object

或者使用静态方法[scriptblock]::create((,如下所示:如何将scriptblock作为启动作业中的参数之一传递

如果没有@js2010为我指明正确的方向,我就不会找到答案,谢谢!

他/她是正确的-出于安全原因,您不能将脚本块传递给作业,但与PowerShell一样,有一个变通方法。

我可以通过从Start-Job切换到Invoke-Command -asjob来实现这一点,但这需要运行和配置WinRM,这在生产中不是一个选项。

$globalConfig = @{
PingAddress = '8.8.8.8';
SystemState = @{
Processors = @{
Namespace = 'rootcimv2';
ClassName = 'Win32_Processor';
SelectProperties = 'Name',  @{ n = 'CpuStatus'; e = { [int]$_.CpuStatus }};
}
}
}
$ScriptBlock = {
param(
[Parameter(Mandatory=$True, Position=1)]
[hashtable]$hashtable
)
Try{
$Response = @{
State = @(); 
Error = $Null
}
$Response.State = Get-CimInstance -ClassName $hashtable.ClassName | Select-Object -Property $hashtable.SelectProperties -ErrorAction Stop
}Catch{
$Response.Error = @{Id = 2; Message = "$($data.Target) query failed: $($_.Exception.Message)"}
}
Return $Response
}
Invoke-Command -ScriptBlock $ScriptBlock -ArgumentList $globalConfig.SystemState.Processors -ComputerName . -AsJob

Name                           Value
----                           -----
Error
State                          @{Name=Intel(R) Core(TM) i7-4710MQ CPU @ 2.50GHz; CpuStatus=1}

这一定是可能的。。。所以我将继续测试解决方案,并将在这里发布我发现的任何内容。

更新

我有这个工作,它有点脏,但它符合项目的需要。我只需使用作业外部的哈希表(作为字符串(构建命令,将命令字符串作为参数传递给作业,然后使用Invoke-Expression:在作业内部运行命令

$globalConfig = @{
PingAddress = '8.8.8.8';
SystemState = @{
Processors = @{
Target = 'Processors'
Namespace = 'rootcimv2';
ClassName = 'Win32_Processor';
SelectProperties = [string]('"Name", @{ n = "CpuStatus"; e = { [int]$_.CpuStatus }}');
}
}
}
$Args = [PSCustomObject]@{
Target = $globalConfig.SystemState.Processors.Target;
Command = "Get-CimInstance -ClassName $($globalConfig.SystemState.Processors.ClassName) -ErrorAction Stop | Select-Object $($globalConfig.SystemState.Processors.SelectProperties) -ErrorAction Stop";
}
$job = Start-Job -Name Processors -ArgumentList $Args -ScriptBlock {
Try{
$Response = @{
State = @(); 
Error = $Null
}
$Response.State = Invoke-Expression -Command $args.Command
}Catch{
$Response.Error = @{Id = 2; Message = "$($Args.Target) query failed: $($_.Exception.Message)"}
}
Return $Response
}
$job | Wait-Job
$job | Receive-Job | ConvertTo-Json -Depth 3

{
"Error":  null,
"State":  {
"Name":  "Intel(R) Core(TM) i7-4710MQ CPU @ 2.50GHz",
"CpuStatus":  1
},
"PSComputerName":  "localhost",
"RunspaceId":  "89f17de1-98b6-4746-a0ba-3e7c47294c61",
"PSShowComputerName":  false
}

相关内容

  • 没有找到相关文章

最新更新