当前位置:网站首页 > 更多 > 玩电脑 > 正文

[玩转系统] Active Directory 对象和 PowerShell 管道

作者:精品下载站 日期:2024-12-14 07:59:47 浏览:16 分类:玩电脑

Active Directory 对象和 PowerShell 管道


这篇文章是我一段时间以来一直想写的。我经常告诉人们,一旦了解了 PowerShell 的核心概念,它就很容易使用,但事实并非总是如此。这是我的朋友 Gladys Kravitz 不久前引起我注意的一个问题。

像她一样,您可能已经编写了这样的 PowerShell 函数来接受管道输入。

Function Get-Foo {
  [cmdletbinding()]
  param(
    [Parameter(Mandatory, ValueFromPipelinebyPropertyName)]
    [string]$Name
  )

  Begin {}
  Process {
    Write-Host "working on $Name" -ForegroundColor Green
  }
  End {}
}

此示例函数查看任何传入对象,并将 Name 属性分配给 Name 参数。您可以通过简单的测试看到结果。

Get-Service bits, winrm | Get-Foo
working on bits
working on winrm

除了显示 $Name 参数的值之外,该函数不执行任何操作。让我们向前迈出一步。

这是一个获取 BITS 服务的简单函数,该服务接受计算机名的管道输入。

Function Get-Bits {
  [cmdletbinding()]
  param(
    [Parameter(Mandatory, ValueFromPipelineByPropertyName)]
    [alias("Name")]
    [string]$Computername
  )

  Begin {}
  Process {
   Write-Host "$Computername" -ForegroundColor yellow
   Get-service -Name bits -ComputerName $computername | Select-Object Machinename,Name,Status
  }
  End {}
}

这基本上按预期工作。我可以指定一个参数值。我还可以通过属性名称从管道获取输入。

[玩转系统] Active Directory 对象和 PowerShell 管道

[玩转系统] Active Directory 对象和 PowerShell 管道

[玩转系统] Active Directory 对象和 PowerShell 管道

是时候看看到底发生了什么了。顺便说一句,如果您将 Get-ADComputer 命令通过管道传递给 Get-Member,PowerShell 会告诉您 Name 属性是一个字符串。

为了更深入地研究,我们转向 Trace-Command cmdlet。您肯定想阅读帮助和示例。在我们的例子中,我们需要了解 PowerShell 对参数绑定做了什么。

[玩转系统] Active Directory 对象和 PowerShell 管道

有很多东西需要了解。当我向下滚动并到达 Get-Bits 函数时,我注意到 PowerShell 对 Computername 的参数绑定做了什么。

[玩转系统] Active Directory 对象和 PowerShell 管道

PowerShell 没有看到字符串。它看到了 ADPropertyValueCollection,但无法转换它,从而导致错误。

[玩转系统] Active Directory 对象和 PowerShell 管道

Function Get-Bits {
#revised version
  [cmdletbinding()]
  param(
    [Parameter(Mandatory, ValueFromPipelineByPropertyName)]
    [alias("Name")]
    [object]$Computername
  )

  Begin {}
  Process {
    write-Host "processing type $($computername.GetType().fullname)" -ForegroundColor yellow
    [Microsoft.ActiveDirectory.Management.ADPropertyValueCollection]::new($Computername)
    switch ($computername.GetType().fullname) {
      "system.string" {$cn = $Computername}
      "microsoft.activedirectory.management.adcomputer" {$cn = $computername.name}
      "Microsoft.ActiveDirectory.Management.ADPropertyValueCollection" {$cn = [Microsoft.ActiveDirectory.Management.ADPropertyValueCollection]::new($computername).name }
      default { $cn = $Computername.computername }
    }
    write-Host "working on $cn" -fore Green
    #  Get-service -Name bits -ComputerName $cn | Select-Object Machinename,Name,Status
  }
  End {}
}

我需要注意为 Computername 获取的对象类型。我不能假设它会是一个字符串。我想验证我的理论。

[玩转系统] Active Directory 对象和 PowerShell 管道

Gladys 和大多数人都认为 AD 对象属性很简单,就像字符串一样。但显然事实并非如此。我还可以从测试中推断,Select-Object 从集合中提取属性并使用它来创建 Selected.Microsoft.ActiveDirectory.Management.ADComputer 对象。

现在我们知道了这一点,我可以修改示例函数以更好地适应来自 Active Directory cmdlet 的管道输入。这将需要使用参数集。

Function Get-Bits {
#with parameter sets
  [cmdletbinding(DefaultParameterSetName = "byString")]
  param(
    [Parameter(Mandatory, ValueFromPipelineByPropertyName, ValueFromPipeline, ParameterSetName = "byString")]
    [alias("Name")]
    [string]$Computername,

    [Parameter(ValueFromPipeline, ParameterSetName = "byADComputer")]
    [Microsoft.ActiveDirectory.Management.ADComputer]$Computer
  )

  Begin {
    Write-Verbose "Starting $($myinvocation.mycommand)"  
  }
  Process {
  Write-Verbose "Using parameter set $($pscmdlet.ParameterSetName)"  
    if ($PSCmdlet.ParameterSetName -eq "byString") {
      $cn = $Computername
    }
    else {
      Write-Verbose "Getting the Name property"
      $cn = $Computer.Name
    }
    Write-Verbose "Getting BITS service from $cn"
    Try {
        Get-Service -Name bits -ComputerName $cn -ErrorAction Stop | 
        Select-Object Machinename, Name, Status
    }
    Catch {
        Write-Warning "Failed to get service status from $CN. $($_.exception.message)"
    }
  }
  End {
    Write-Verbose "Ending $($myinvocation.mycommand)"  
  }
}

此版本的函数将通过 Computername 的属性名称或别名 Name 获取管道输入。或者,它将处理 ADComputer 对象。在 Process 块中,我可以获得正确的计算机名值以传递给 Get-Service。这个版本为我提供了我所期待的 PowerShell 体验。

[玩转系统] Active Directory 对象和 PowerShell 管道

[玩转系统] Active Directory 对象和 PowerShell 管道

至少 Gladys 知道她没有发疯,并且有解决方案可以满足她的 Active Directory 脚本需求。我鼓励您尝试 Trace-Command。当您下次遇到问题并想要减少额头上的瘀伤数量时,它可能会派上用场。

与往常一样,欢迎提出意见和反馈。

您需要 登录账户 后才能发表评论

取消回复欢迎 发表评论:

关灯