选择不存在的属性时没有错误

时间:2015-10-02 10:53:49

标签: powershell powershell-v4.0 select-object

我希望PowerShell在尝试选择不存在的属性时抛出错误,但我得到空列作为输出。例如:

$ErrorActionPreference=[System.Management.Automation.ActionPreference]::Stop;
Set-StrictMode -Version 'Latest'
Get-Process *ex* | Select-Object Id,ProcessName,xxx

   Id ProcessName   xxx
   -- -----------   ---
 9084 explorer
11404 procexp

我写了一个脚本,用Import-Csv导入多个文本文件,但这些文件中的标题可能会更改,我最终会将空列加载到系统中。

编辑: 这就是我检查标题是否匹配的方式:

$csv = Import-Csv -Delimiter ';' -Path $file.FullName 
$FileHeaders = @(($csv | Get-Member -MemberType NoteProperty).Name) 
if (Compare-Object $ProperHeaders $FileHeaders) {'err'} else {'ok'}

我知道这是PowerShell的工作方式,但Set-StrictMode文档对我来说确实有点误导,正如@Matt所说。我只是希望Select-Object有一些“-NoNewImplicitProps”或“-ReadOnlyPipeline”开关可以为我做这个工作:)。谢谢你的回答。

4 个答案:

答案 0 :(得分:4)

您实际上正在使用some people would call a feature。这是在所有数组成员上使用Add-Member添加空列的简单再现。

对于Import-CSV,在这种情况下您要执行的操作是在调用它们的Select之前检查属性名称​​。

$data = Import-csv C:\Temp\file.csv 
$props = $data | Get-member -MemberType 'NoteProperty'  | Select-Object -ExpandProperty Name

我可以看到文档有点misleading when it says for Set-StrictMode

  

禁止引用对象的不存在的属性。

但在这种情况下,您不是要尝试获取属性引用,而是使用Select-Object cmdlet的函数。以下内容会产生错误

PS C:\Users\mcameron> Set-StrictMode -Version 'Latest'
(Get-Process *ex*).Bagels
The property 'Bagels' cannot be found on this object. Verify that the property exists.
At line:2 char:1
+ (Get-Process *ex*).Bagels
+ ~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (:) [], PropertyNotFoundException
    + FullyQualifiedErrorId : PropertyNotFoundStrict

答案 1 :(得分:4)

PowerShell将不存在的属性扩展为$null的行为与设计相同。 AFAICS你唯一能做的就是明确检查是否所有属性都存在:

$props = 'Id', 'ProcessName', 'xxx'

$p = Get-Process *ex*
$missing = $p | Get-Member -Type *property |
           Select-Object -Expand Name |
           Compare-Object -Reference $props |
           Where-Object { $_.SideIndicator -eq '<=' } |
           Select-Object -Expand InputObject

if ($missing) {
  throw "missing property $missing."
} else {
  $p | Select-Object $props
}

当然,您可以将其包装在自定义函数中:

function Select-ObjectStrict {
  [CmdletBinding()]
  Param(
    [Parameter(
      Position=0,
      Mandatory=$true,
      ValueFromPipeline=$true,
      ValueFromPipelineByPropertyName=$true
    )]$InputObject,

    [Parameter(
      Position=1,
      Mandatory=$true
    )][string[]]$Property
  )

  Process {
    $missing = $InputObject | Get-Member -Type *property |
               Select-Object -Expand Name |
               Compare-Object -Reference $Property |
               Where-Object { $_.SideIndicator -eq '<=' } |
               Select-Object -Expand InputObject

    if ($missing) {
      throw "missing property $missing."
    } else {
      $InputObject | Select-Object $Property
    }
  }
}

所以它可以像这样使用:

Get-Process *ex* | Select-ObjectStrict -Property 'Id', 'ProcessName', 'xxx'

答案 2 :(得分:0)

这样的东西......?

$props = 'Id','ProcessName','xxx'
$availableProps = Get-Process *ex*|Get-Member -MemberType Properties | Select -ExpandProperty Name
$missingProps = $props | Where-Object {-not ($availableProps -contains $_)}
if ($missingProps) {
  Write-Error "invalid property(s) $missingProps"
  throw { [System.Management.Automation.PropertyNotFoundException] }
}

Get-Process *ex* | Select-Object $props

答案 3 :(得分:0)

如果你想在选择不存在的属性时收到错误
使用:

Set-StrictMode -Version Latest<br>
$Global:ErrorActionPreference = 'Stop'<br>