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

[玩转系统] 创建您自己的 PowerShell 命令

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

创建您自己的 PowerShell 命令


[玩转系统] 创建您自己的 PowerShell 命令

除了节省大量输入之外,优点是通过使用代理函数,您可以利用包装的 cmdlet 的功能和参数。但也许看一个例子会有所帮助。将 Get-CommandMetadata 函数加载到 PowerShell ISE 后,我运行以下命令:

get-commandmetadata get-ciminstance -NoHelp -NewName Get-CimOS

我将不使用 CDXML 或编写自己的函数来调用 Get-Cimstance,而是创建一个旨在检索操作系统信息的 Get-Ciminstance 代理。这就是我的开始。

#requires -version 4.0

Function Get-CimOS {

[CmdletBinding(DefaultParameterSetName='ClassNameComputerSet')]
 param(
     [Parameter(ParameterSetName='QuerySessionSet', Mandatory=$true, ValueFromPipeline=$true)]
     [Parameter(ParameterSetName='CimInstanceSessionSet', Mandatory=$true, ValueFromPipeline=$true)]
     [Parameter(ParameterSetName='ClassNameSessionSet', Mandatory=$true, ValueFromPipeline=$true)]
     [Parameter(ParameterSetName='ResourceUriSessionSet', Mandatory=$true, ValueFromPipeline=$true)]
     [Microsoft.Management.Infrastructure.CimSession[]]
  $CimSession, 
     [Parameter(ParameterSetName='ClassNameSessionSet', Mandatory=$true, Position=0, ValueFromPipelineByPropertyName=$true)]
     [Parameter(ParameterSetName='ClassNameComputerSet', Mandatory=$true, Position=0, ValueFromPipelineByPropertyName=$true)]
     [string]
  $ClassName, 
     [Parameter(ParameterSetName='CimInstanceSessionSet')]
     [Parameter(ParameterSetName='CimInstanceComputerSet')]
     [Parameter(ParameterSetName='QuerySessionSet', ValueFromPipelineByPropertyName=$true)]
     [Parameter(ParameterSetName='QueryComputerSet', ValueFromPipelineByPropertyName=$true)]
     [Parameter(ParameterSetName='ResourceUriSessionSet', Mandatory=$true, ValueFromPipelineByPropertyName=$true)]
     [Parameter(ParameterSetName='ResourceUriComputerSet', Mandatory=$true, ValueFromPipelineByPropertyName=$true)]
     [uri]
  $ResourceUri, 
     [Parameter(ParameterSetName='QueryComputerSet', ValueFromPipelineByPropertyName=$true)]
     [Parameter(ParameterSetName='ResourceUriComputerSet', ValueFromPipelineByPropertyName=$true)]
     [Parameter(ParameterSetName='CimInstanceComputerSet')]
     [Parameter(ParameterSetName='ClassNameComputerSet', ValueFromPipelineByPropertyName=$true)]
     [Alias('CN','ServerName')]
     [string[]]
  $ComputerName, 
     [Parameter(ParameterSetName='ResourceUriSessionSet')]
     [Parameter(ParameterSetName='ClassNameSessionSet')]
     [Parameter(ParameterSetName='ResourceUriComputerSet')]
     [Parameter(ParameterSetName='ClassNameComputerSet')]
     [switch]
  $KeyOnly, 
     [Parameter(ParameterSetName='ClassNameSessionSet', ValueFromPipelineByPropertyName=$true)]
     [Parameter(ParameterSetName='ResourceUriComputerSet', ValueFromPipelineByPropertyName=$true)]
     [Parameter(ParameterSetName='QuerySessionSet', ValueFromPipelineByPropertyName=$true)]
     [Parameter(ParameterSetName='ClassNameComputerSet', ValueFromPipelineByPropertyName=$true)]
     [Parameter(ParameterSetName='QueryComputerSet', ValueFromPipelineByPropertyName=$true)]
     [Parameter(ParameterSetName='ResourceUriSessionSet', ValueFromPipelineByPropertyName=$true)]
     [string]
  $Namespace, 
     [Alias('OT')]
     [uint32]
  $OperationTimeoutSec, 
     [Parameter(ParameterSetName='CimInstanceComputerSet', Mandatory=$true, Position=0, ValueFromPipeline=$true)]
     [Parameter(ParameterSetName='CimInstanceSessionSet', Mandatory=$true, Position=0, ValueFromPipeline=$true)]
     [Alias('CimInstance')]
     [ciminstance]
  $InputObject, 
     [Parameter(ParameterSetName='QueryComputerSet', Mandatory=$true, ValueFromPipelineByPropertyName=$true)]
     [Parameter(ParameterSetName='QuerySessionSet', Mandatory=$true, ValueFromPipelineByPropertyName=$true)]
     [string]
  $Query, 
     [Parameter(ParameterSetName='QueryComputerSet', ValueFromPipelineByPropertyName=$true)]
     [Parameter(ParameterSetName='QuerySessionSet', ValueFromPipelineByPropertyName=$true)]
     [Parameter(ParameterSetName='ClassNameSessionSet', ValueFromPipelineByPropertyName=$true)]
     [Parameter(ParameterSetName='ClassNameComputerSet', ValueFromPipelineByPropertyName=$true)]
     [string]
  $QueryDialect, 
     [Parameter(ParameterSetName='ResourceUriSessionSet')]
     [Parameter(ParameterSetName='QueryComputerSet')]
     [Parameter(ParameterSetName='QuerySessionSet')]
     [Parameter(ParameterSetName='ResourceUriComputerSet')]
     [Parameter(ParameterSetName='ClassNameComputerSet')]
     [Parameter(ParameterSetName='ClassNameSessionSet')]
     [switch]
  $Shallow, 
     [Parameter(ParameterSetName='ClassNameSessionSet', ValueFromPipelineByPropertyName=$true)]
     [Parameter(ParameterSetName='ClassNameComputerSet', ValueFromPipelineByPropertyName=$true)]
     [Parameter(ParameterSetName='ResourceUriSessionSet', ValueFromPipelineByPropertyName=$true)]
     [Parameter(ParameterSetName='ResourceUriComputerSet', ValueFromPipelineByPropertyName=$true)]
     [string]
  $Filter, 
     [Parameter(ParameterSetName='ClassNameComputerSet', ValueFromPipelineByPropertyName=$true)]
     [Parameter(ParameterSetName='ResourceUriComputerSet', ValueFromPipelineByPropertyName=$true)]
     [Parameter(ParameterSetName='ClassNameSessionSet', ValueFromPipelineByPropertyName=$true)]
     [Parameter(ParameterSetName='ResourceUriSessionSet', ValueFromPipelineByPropertyName=$true)]
     [Alias('SelectProperties')]
     [string[]]
  $Property) 
 begin
 {
     try {
         $outBuffer = $null
         if ($PSBoundParameters.TryGetValue('OutBuffer', [ref]$outBuffer))
         {
             $PSBoundParameters['OutBuffer'] = 1
         }
         $wrappedCmd = $ExecutionContext.InvokeCommand.GetCommand('Get-CimInstance', [System.Management.Automation.CommandTypes]::Cmdlet)
         $scriptCmd = {& $wrappedCmd @PSBoundParameters }
         $steppablePipeline = $scriptCmd.GetSteppablePipeline($myInvocation.CommandOrigin)
         $steppablePipeline.Begin($PSCmdlet)
     } catch {
         throw
     }
 }
 
 process
 {
     try {
         $steppablePipeline.Process($_)
     } catch {
         throw
     }
 }
 
 end
 {
     try {
         $steppablePipeline.End()
     } catch {
         throw
     }
 }
 <#
 
 .Synopsis
 PUT SYNTAX HERE
 .Description
 PUT DESCRIPTION HERE
 .Notes
 Created:	9/8/2014 
 
 .Example
 PS C:\> Get-CimOS
 
 .Link
 Get-CimInstance
 
 #>
 

} #end function Get-CimOS

与任何 PowerShell 脚本项目一样,您必须考虑谁将运行您的命令以及他们可能有什么期望。在我的示例中,我只是希望能够指定计算机名称或 CIM 会话并从 Win32_Operatingsystem 类检索信息。因此,首先我可以删除除 Computername 和 CIMSession 之外的所有参数定义。我还将保留 OperationTimeOut 参数以防万一。正如您在代码示例中看到的,Get-CimInstance 还具有许多参数集。同样,我可以删除对我不打算使用的引用。

这是我修改后的参数定义。

[CmdletBinding(DefaultParameterSetName='ClassNameComputerSet')]
param(
    [Parameter(Position=0,ParameterSetName='CimInstanceSessionSet', Mandatory=$true, ValueFromPipeline=$true)]
    [Microsoft.Management.Infrastructure.CimSession[]]$CimSession,

    [Parameter(Position=0,ParameterSetName='ClassNameComputerSet', ValueFromPipelineByPropertyName=$true)]
    [Alias('CN','ServerName')]
    [string[]]$ComputerName = $env:Computername,

    [Alias('OT')]
    [uint32]$OperationTimeoutSec
    )

我所做的一项更改是为本地计算机指定计算机名的默认值。我这样做是为了让 PSComputername 属性始终有一个值。

PS C:\> get-ciminstance win32_bios | select name,pscomputername

name                                                        PSComputerName
----                                                        --------------
76CN38WW


PS C:\> get-ciminstance win32_bios -comp $env:computername | select name,pscomputername

name                                                        PSComputerName
----                                                        --------------
76CN38WW                                                    WIN81-ENT-01

但您可能想知道,类名怎么样?这就是乐趣的开始。我将把其他参数硬编码到函数中。

#Add hard-coded parameters
$PSBoundParameters.Add("Classname","win32_operatingsystem")
$PSBoundParameters.Add("Namespace","root\cimv2")

$wrappedCmd = $ExecutionContext.InvokeCommand.GetCommand('Get-CimInstance', [System.Management.Automation.CommandTypes]::Cmdlet)

当执行包装的命令时,它将使用这些值,这就是我想要的。此时,我可以保存该函数并运行它。但输出与我运行 Get-Ciminstance 时的输出相同,并且我心里有一个特定的输出。就是这样。

首先,复制并粘贴新版本的 $scriptCmd 行。注释掉原来的行。

# $scriptCmd = {& $wrappedCmd @PSBoundParameters }

我需要做的是创建自己的脚本命令,它必须是单个管道表达式。

$scriptCmd = {
    #select whatever Win32_OperatingSystem properties you need
    & $wrappedCmd @PSBoundParameters | 
    Select-Object @{Name="Computername";Expression={$_.CSName}},
    @{Name="OS";Expression={$_.Caption}},Version,
    @{Name="64bit";Expression={
    if ($_.OSArchitecture -match "64") {
        $True
    }
    else {
        $False
    }}}, 
    @{Name="SvcPack";Expression={$_.CSDVersion}},InstallDate
} #scriptcmd

我仍然希望运行封装的 Get-Ciminstance 命令,但随后我会将结果通过管道传输到 Select-Object 并指定一些自定义属性。这就是我的主要更改的范围,尽管我还将添加一些额外的 Write-Verbose 行以进行跟踪和故障排除。更新基于评论的帮助后,这是我的最终命令。

#requires -version 4.0

#this version selects the properties I want

Function Get-CIMOS {

<#
.Synopsis
Get operating system information.
.Description
This is a proxy version of Get-CimInstance designed to get operating system information from one or more computers.
.Notes
Last Updated:	9/4/2014 

Learn more:
 PowerShell in Depth: An Administrator's Guide (http://www.manning.com/jones6/)
 PowerShell Deep Dives (http://manning.com/hicks/)
 Learn PowerShell in a Month of Lunches (http://manning.com/jones3/)
 Learn PowerShell Toolmaking in a Month of Lunches (http://manning.com/jones4/)
 PowerShell and WMI (http://www.manning.com/siddaway2/)

  ****************************************************************
  * DO NOT USE IN A PRODUCTION ENVIRONMENT UNTIL YOU HAVE TESTED *
  * THOROUGHLY IN A LAB ENVIRONMENT. USE AT YOUR OWN RISK.  IF   *
  * YOU DO NOT UNDERSTAND WHAT THIS SCRIPT DOES OR HOW IT WORKS, *
  * DO NOT USE IT OUTSIDE OF A SECURE, TEST SETTING.             *
  ****************************************************************

.Example
PS C:> get-cimos chi-dc04

Computername   : CHI-DC04
OS             : Microsoft Windows Server 2012 Datacenter
Version        : 6.2.9200
SvcPack        :
InstallDate    : 9/10/2012 12:41:57 PM

.Example
PS C:\> get-cimsession | get-cimos | out-gridview -title "OS Report"
.Link
Get-CimInstance
#>

[CmdletBinding(DefaultParameterSetName='ClassNameComputerSet')]
param(
    [Parameter(Position=0,ParameterSetName='CimInstanceSessionSet', Mandatory=$true, ValueFromPipeline=$true)]
    [Microsoft.Management.Infrastructure.CimSession[]]$CimSession,

    [Parameter(Position=0,ParameterSetName='ClassNameComputerSet', ValueFromPipelineByPropertyName=$true)]
    [Alias('CN','ServerName')]
    [string[]]$ComputerName = $env:Computername,

    [Alias('OT')]
    [uint32]$OperationTimeoutSec
    )

begin
{
    #add my own verbose output
    Write-Verbose -Message "Starting $($MyInvocation.Mycommand)"  
    Write-verbose $PSCmdlet.ParameterSetName

    try {
        $outBuffer = $null
        if ($PSBoundParameters.TryGetValue('OutBuffer', [ref]$outBuffer))
        {
            $PSBoundParameters['OutBuffer'] = 1
        }

        #Add hard-coded parameters
        $PSBoundParameters.Add("Classname","win32_operatingsystem")
        $PSBoundParameters.Add("Namespace","root\cimv2")

        $wrappedCmd = $ExecutionContext.InvokeCommand.GetCommand('Get-CimInstance', [System.Management.Automation.CommandTypes]::Cmdlet)
       
       #the original line
       # $scriptCmd = {& $wrappedCmd @PSBoundParameters }

       #my modified scriptblock. The scriptblock can only contain a single pipelined expression
        $scriptCmd = {
         #select whatever Win32_OperatingSystem properties you need
         & $wrappedCmd @PSBoundParameters | 
         Select-Object @{Name="Computername";Expression={$_.CSName}},
         @{Name="OS";Expression={$_.Caption}},Version,
         @{Name="64bit";Expression={
          if ($_.OSArchitecture -match "64") {
            $True
          }
          else {
            $False
          }}}, 
         @{Name="SvcPack";Expression={$_.CSDVersion}},InstallDate
         } #scriptcmd

        $steppablePipeline = $scriptCmd.GetSteppablePipeline($myInvocation.CommandOrigin)

        Write-Verbose "Begin steppable pipeline"
        $steppablePipeline.Begin($PSCmdlet)
    } catch {
        throw
    }
} #begin block

process
{
    try {
        Write-Verbose "Processing"
        if ($PSCmdlet.ParameterSetName -eq 'ClassNameComputerSet') {
            $inputs = $ComputerName
        }
        else {
            $inputs = $cimSession.Computername
        }

        foreach ($computer in $inputs) {
            Write-Verbose "...$computer"
        }
        
   
        $steppablePipeline.Process($_) 

    } catch {
        throw
    }
} #process block

end
{
    Write-Verbose -Message "Ending $($MyInvocation.Mycommand)" 

    try {
        $steppablePipeline.End() 
    } catch {
        throw
    }
} #end block
} #end function Get-CIMOS

现在来测试一下:

PS C:\> get-cimos

Computername : WIN81-ENT-01
OS           : Microsoft Windows 8.1 Enterprise
Version      : 6.3.9600
64bit        : True
SvcPack      :
InstallDate  : 11/26/2013 1:08:31 PM

我可以指定一个计算机名:

PS C:\> get-cimos -ComputerName chi-dc04

Computername : CHI-DC04
OS           : Microsoft Windows Server 2012 Datacenter
Version      : 6.2.9200
64bit        : True
SvcPack      :
InstallDate  : 9/10/2012 12:41:57 PM

或者使用 CIMSession。

PS C:\> get-cimsession | get-cimos |out-gridview -title "OS Report"

[玩转系统] 创建您自己的 PowerShell 命令

我无需编写任何代码即可使用 CIMSession。我让包装的 cmdlet 为我处理一切。最终的结果是我现在有了一个非常完整的 PowerShell 工具,并且不需要花费太多时间来创建。我可能花在写基于评论的帮助上的时间比任何事情都多。

希望这能让您了解如何将 PowerShell 工具制作提升到一个新的水平。

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

取消回复欢迎 发表评论:

关灯