4

我希望 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

4 回答 4

5

您实际上正在使用某些人所说的功能Add-Member这是在所有数组成员上使用以添加空列的更简单的演绎。

在这种情况下,Import-CSV您要做的是在调用它们的位置之前检查属性名称。Select

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

我可以看到文档中说的有点误导Set-StrictMode

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

但在这种情况下,您不是尝试获取属性引用,而是使用Select-Objectcmdlet 的功能。以下会产生错误

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
于 2015-10-02T11:40:54.927 回答
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'
于 2015-10-02T11:44:36.713 回答
1

像这样的东西……?

$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
于 2015-10-02T12:08:31.327 回答
0

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

Set-StrictMode -Version Latest<br>
$Global:ErrorActionPreference = 'Stop'<br>
于 2021-02-17T21:53:52.213 回答