powershell 具有常量块的Powershell函数模板,您可以在从命令行调用和添加任何类型的参数时覆盖它

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了powershell 具有常量块的Powershell函数模板,您可以在从命令行调用和添加任何类型的参数时覆盖它相关的知识,希望对你有一定的参考价值。

<#
    .SYNOPSIS
        Template of Function which takes any number of parameters 


    .DESCRIPTION
        Template of Function which takes any number of parameters. 
        Function has default parameter block $defaults which can be overridden by command line parameters.
        Function accumulates command line parameters and merges them with default parameters to the $__ENV.env hashtable.


    .PARAMETER ShowProperty
        Select one of 5 views of resulting parameters: Env, Named, Positional, Default and All (TODO)


    .INPUTS
        Does not accept inputs from the pipeline


    .OUTPUTS
        Outputs [PSCustomObject] with all the data about resulting parameters set.


    .NOTES
        (c) 2017 Andriy Melnyk  https://guthub.com/TurboBasic


    .LINK
        #Merge-Hastables


    .FUNCTIONALITY
        Use this for testing and learning how Powershell processes advanced function parameters.  Due to fully working and universal 
        feature set it is easy and convenient to use as a template function


    .EXAMPLE
        In all examples we assume that the Function doesn't have positional parameters and default parameters block looks as follows:
          $defaults = @{   
              SERVER         = 'http://localhost'
              PORT           = 8080
              SOME_CONSTANT  = 0xFF
              PRODUCTION     = $False
              showProperty   = 'Env'
          }

        PS C:\> Abstract-FunctionWithConfigBlockTemplate

        Name                           Value
        ----                           -----
        PORT                           8080
        SOME_CONSTANT                  255
        SERVER                         http://localhost
        PRODUCTION                     False
        showProperty                   Env


    .EXAMPLE
        By default, resulting set includes only named parameters:

        PS C:\> Abstract-FunctionWithConfigBlockTemplate -a 2 $true 4

        Name                           Value
        ----                           -----
        PRODUCTION                     False
        SERVER                         http://localhost
        SOME_CONSTANT                  255
        showProperty                   Env
        PORT                           8080
        a                              2


    .EXAMPLE
        PS C:\> Abstract-FunctionWithConfigBlockTemplate -server 'https://8.8.8.8', 'http://local.dev' -port 80 -production

        Name                           Value
        ----                           -----
        PRODUCTION                     True
        SERVER                         {https://8.8.8.8, http://local.dev}
        SOME_CONSTANT                  255
        showProperty                   Env
        PORT                           80


    .EXAMPLE
        Show non-default Named parameters

        PS C:\> Abstract-FunctionWithConfigBlockTemplate -server 'https://8.8.8.8','http://localhost' -port 80 -production -showproperty named

        Key              Value
        ---              -----
        __restParameters {-server, https://8.8.8.8 http://localhost, -port, 80...}
        server            {https://8.8.8.8, http://localhost}
        port             80
        production       True
        showproperty     named

#>

Function Abstract-FunctionWithConfigBlockTemplate {
    [OUTPUTTYPE( [string[]] )]
    [CMDLETBINDING( PositionalBinding=$False )] 
    PARAM(

      #region Constants block. 
          [PARAMETER()]
          [VALIDATESCRIPT({
            If( $_ -is [System.Collections.Hashtable] ) 
                { $True } 
            Else 
                { Throw "'$_' should be a Hashtable!" } 
          })]
          $defaults = @{   
              SERVER         = 'http://localhost'
              PORT           = 8080
              SOME_CONSTANT  = 0xFF
              PRODUCTION     = $False
              showProperty   = 'Env'
          },

            # listEnv        = $True 
            # listNamed      = $False
            # listDefault    = $False
            # listPositional = $False

      #endregion 
   

      #region Standard parameters

       <# 
            add `[PARAMETER( Position=<number> )]` if you need positional parameter.
            In this case custom parameters will start to accumulate after the last positional parameter
            and you will have to include postional parameters to command line
            
            Eg. if you have 2 positional parameters  
                [PARAMETER(Position=0)] $a
                [PARAMETER(Position=1)] $b
            then the bindings for the following commands will look as follows:
            
            PS> Abstract-FunctionWithConfigBlockTemplate -customArg 2 3 4
            $__ENV.customArg = 2
            $a = 3
            $b = 4
            
            PS> Abstract-FunctionWithConfigBlockTemplate 2 3 4
            $__ENV.anonymousParameter = 4
            $a = 2
            $b = 3
        #>
      
          [PARAMETER( ValueFromPipeline )]     # add `Position=<number>` if needed
          [Int[]] 
          $SomeIntegerParameter = 137,

          [PARAMETER( )]                       # add `Position=<number>` if needed
          [String] 
          $SomeTextParameter = 'Default text',
      
      #endregion


      #region Custom parameters

          [PARAMETER( ValueFromRemainingArguments )]
          [Object[]] 
          $__restParameters

      #endregion  
    )

  BEGIN {

      # Current parameter binding state
      #
      # Ready:  Previous parameter completely read. Ready to read next named or positional 
      #         parameter
      #
      # ParameterName: 
      #         Name of parameter has been read, expecting its value, if no value $True is default
      #
      enum ParameterBindingState { 
              Ready
              ParameterName
      }

      # Global parameter binding state depends on current parameter state and current text token
      # (this is current parameter name) and previously read parameter name, if any
      $bindingState = @{
        State =   [ParameterBindingState]::Ready
        Name  =   ''
      }


      $Parameters = Foreach ($Parameter in $__restParameters) {
          if( $Parameter -match '^-([a-z_][a-z0-9_]*)$' ) { 

              $bindingState.Name = $Matches[1]
              New-Variable -Name $bindingState.Name -Value $True
              $PSBoundParameters.Add( $bindingState.Name, $True ) | Out-Null
              $bindingState.State = [ParameterBindingState]::ParameterName

          } elseif( $bindingState.State -eq [ParameterBindingState]::ParameterName ) { 

              $Value = $foreach.Current
              Set-Variable -Name $bindingState.Name -Value $Value
              $PSBoundParameters[$bindingState.Name] = $Value
              $bindingState.State = [ParameterBindingState]::Ready
              $bindingState.Name = ''

          } elseif( $bindingState.State -eq [ParameterBindingState]::Ready ) { 
              $Parameter 
          }
      }


      $__ENV = @{}
      $__ENV.Add('Named', $psBoundParameters)
      $__ENV.Add('Positional', $Parameters)
      $__ENV.Add('Default', $defaults )      
  }


  PROCESS {    
    $null = 'Do something with arguments'
  }


  END {
    $__ENV.Add( 'Env', (Merge-Hashtables $__ENV.Default $__ENV.Named) )
    $__ENV.Env.Remove('__restParameters')

    # $__ENV | Format-Table -Autosize -Wrap `
    #            Name, @{ Label = "Value"; Expression = { ConvertTo-JSON $_.Value } } 
    
    $includeProperties = @()
    $includeProperties += ,'Env'        * $__ENV.Env.listEnv
    $includeProperties += ,'Named'      * $__ENV.Env.listNamed
    $includeProperties += ,'Default'    * $__ENV.Env.listDefault
    $includeProperties += ,'Positional' * $__ENV.Env.listPositional
    ([psCustomObject]$__ENV)  | Select -Property $includeProperties | Out-Null

    ([psCustomObject]$__ENV)  | Select -ExpandProperty $__ENV.Env.showProperty

  }
} 
# some short examples
# (Abstract-FunctionWithConfigBlockTemplate 1 'tty' -15 @(1,2),2  @('cdf',5),1)
# (Abstract-FunctionWithConfigBlockTemplate 1 'tty' -15 @(1,2),2  @('cdf',5),1).Positional
# (Abstract-FunctionWithConfigBlockTemplate 1 'tty' -15 @(1,2),2  @('cdf',5),1).Positional[2]
# (Abstract-FunctionWithConfigBlockTemplate 1 'tty' -15 @(1,2),2  @('cdf',5),1).Positional[3][1]
# (Abstract-FunctionWithConfigBlockTemplate 1 'tty' -15 @(1,2),2  @('cdf',5),1).Named
# (Abstract-FunctionWithConfigBlockTemplate 'tty' -x -15 -yy @(1,2),2  -zz -zzn @('cdf',5),1 -zlast).Named

以上是关于powershell 具有常量块的Powershell函数模板,您可以在从命令行调用和添加任何类型的参数时覆盖它的主要内容,如果未能解决你的问题,请参考以下文章

powershell 来自https://stackoverflow.com/questions/31051103/how-to-export-a-class-in-powershell-v5-mod

PowerShe 使用证书签名 ll脚本

使用以下逻辑编写 Powershell 脚本的指南 [关闭]

使用Powershell管理Linux 下的 SQL Server

通过 PHP 使用 Exchange 管理单元执行 powershell 脚本

哪些方法可以绕过PowerShell Execution Policy?