如何在提示之前传递读取主机输入?

时间:2019-05-16 18:14:35

标签: powershell

假设我有此cmdlet

[CmdletBinding(DefaultParameterSetName='View')]
Param(
    [Parameter(ParameterSetName='ChangeOne', Mandatory=$true)]
    [Switch]$ChangeOne,

    [Parameter(ParameterSetName='ChangeAll', Mandatory=$true)]
    [Switch]$ChangeAll,

    [Parameter(ParameterSetName='View', Mandatory=$false)]
    [Switch]$View
)

现在我有一些条件语句,如下:

if ($ChangeOne)
{
    $input = (Read-Host -prompt "Database")

    if (!$input) 
    { 
        Write-Host "`r`n`You MUST enter a DB Name! 1 more try...`r`n" -foregroundcolor cyan -backgroundcolor black

        $input = (Read-Host -prompt "Database")

        if (!$input) 
        { 
            Write-Host "`r`nNo DB Name entered...exiting script`r`n" -foregroundcolor magenta -backgroundcolor black    
            Write-host "----------------------------END of Script------------------------------"
            exit 1
        }
    }
}

这很好用,除了现在我正尝试使用TFS中的WinRM调用此脚本,并且TFS将不会与Read-Host交互...相反,它将仅接受诸如:

的直接参数。
  

script1.ps1 -ChangeOne数据库输入1

我的问题是,如何允许在没有提示的情况下在命令行中输入Read-Host?我只是想一种让TFS接受读取主机预定义输入的方法

我会想到这样的东西,但这不会起作用,因为param要求它必须位于脚本的顶部...

if ($ChangeOne)
{
    param([string]$input)

    if (!$input) 
    { 
        Write-Host "`r`n`You MUST enter a DB Name! 1 more try...`r`n" -foregroundcolor cyan -backgroundcolor black

        $input = param([string]$input)

        if (!$input) 
        { 
            Write-Host "`r`nNo DB Name entered...exiting script`r`n" -foregroundcolor magenta -backgroundcolor black    
            Write-host "----------------------------END of Script------------------------------"
            exit 1
        }
    }
}

2 个答案:

答案 0 :(得分:1)

要添加DynamicParam,您需要逐步构建对象。我使用以下模板创建我的模板,需要注意的主要地方是$ParameterName[String],您可以根据需要进行更改。

function MyFunction
{
    [CmdletBinding(DefaultParameterSetName='View')]
    Param(
        [Parameter(ParameterSetName='ChangeOne', Mandatory=$true)]
        [Switch]$ChangeOne,

        [Parameter(ParameterSetName='ChangeAll', Mandatory=$true)]
        [Switch]$ChangeAll,

        [Parameter(ParameterSetName='View', Mandatory=$false)]
        [Switch]$View
    )

    DynamicParam
    {
        if($ChangeOne)
        {
            #OutputObject
            $ParameterName = 'DatabaseInput'
            $RuntimeParameterDictionary = New-Object System.Management.Automation.RuntimeDefinedParameterDictionary
            $AttributeCollection = New-Object System.Collections.ObjectModel.Collection[System.Attribute]
            $ParameterAttribute = New-Object System.Management.Automation.ParameterAttribute
            $ParameterAttribute.Mandatory = $true
            $AttributeCollection.Add($ParameterAttribute)
            $RuntimeParameter = New-Object System.Management.Automation.RuntimeDefinedParameter($ParameterName, [string], $AttributeCollection)
            $RuntimeParameterDictionary.Add($ParameterName, $RuntimeParameter)
            return $RuntimeParameterDictionary
        }
    }
}

如果要根据某些预定义值验证输入,则可以创建一个数组(可以硬编码或动态生成)。

请注意,添加了以下几行

 $ValidateSetAttribute = New-Object System.Management.Automation.ValidateSetAttribute($ValidationArray)
 $AttributeCollection.Add($ValidateSetAttribute)

$ValidationArray = 1..9

下面是完整的DynamicParam

   DynamicParam
    {
        if($ChangeOne)
        {
            #Array of values to validate against
            $ValidationArray = 1..9

            #OutputObject
            $ParameterName = 'DatabaseInput'
            $RuntimeParameterDictionary = New-Object System.Management.Automation.RuntimeDefinedParameterDictionary
            $AttributeCollection = New-Object System.Collections.ObjectModel.Collection[System.Attribute]
            $ParameterAttribute = New-Object System.Management.Automation.ParameterAttribute
            $ParameterAttribute.Mandatory = $true
            $AttributeCollection.Add($ParameterAttribute)
            $ValidateSetAttribute = New-Object System.Management.Automation.ValidateSetAttribute($ValidationArray)
            $AttributeCollection.Add($ValidateSetAttribute)
            $RuntimeParameter = New-Object System.Management.Automation.RuntimeDefinedParameter($ParameterName, [string], $AttributeCollection)
            $RuntimeParameterDictionary.Add($ParameterName, $RuntimeParameter)
            return $RuntimeParameterDictionary
        }
    }

这是我重复使用的两个模板。使用intellisense在PowerShell ISE中进行测试。

这些“模板”可能会被清理掉,所以那里可能会有更好的例子。

修改

您可以手动指定参数的位置,我们需要使用$ParameterAttribute.Position = 1在参数上设置position属性。我还在开关上将位置设置为0,建议您手动设置所有参数的位置,以使您安心。

我之前也没有提到您需要通过$PsBoundParameters访问值。在此示例中,我将它们分配给了begin块中的变量。这使它们在整个函数中更易于引用,但是您可以只使用$PsBoundParameters["DatabaseInput"]

function MyFunction
{
    [CmdletBinding(DefaultParameterSetName='View',PositionalBinding=$false)]
    Param(
        [Parameter(ParameterSetName='ChangeOne', Mandatory=$true, Position=0)]
        [Switch]$ChangeOne,

        [Parameter(ParameterSetName='ChangeAll', Mandatory=$true, Position=0)]
        [Switch]$ChangeAll,

        [Parameter(ParameterSetName='View', Mandatory=$false, Position=0)]
        [Switch]$View
    )

    DynamicParam
    {
        if($ChangeOne)
        {
            #Array of values to validate against
            $ValidationArray = 1..9

            #OutputObject
            $ParameterName = 'DatabaseInput'
            $RuntimeParameterDictionary = New-Object System.Management.Automation.RuntimeDefinedParameterDictionary
            $AttributeCollection = New-Object System.Collections.ObjectModel.Collection[System.Attribute]
            $ParameterAttribute = New-Object System.Management.Automation.ParameterAttribute
            $ParameterAttribute.Mandatory = $true
            $ParameterAttribute.Position = 1
            $AttributeCollection.Add($ParameterAttribute)


            $ValidateSetAttribute = New-Object System.Management.Automation.ValidateSetAttribute($ValidationArray)
            $AttributeCollection.Add($ValidateSetAttribute)

            $RuntimeParameter = New-Object System.Management.Automation.RuntimeDefinedParameter($ParameterName, [string], $AttributeCollection)
            $RuntimeParameterDictionary.Add($ParameterName, $RuntimeParameter)
            return $RuntimeParameterDictionary
        }
    }

    begin
    {
        $ChangeOne = $PsBoundParameters["ChangeOne"]
        $ChangeAll = $PsBoundParameters["ChangeAll"]
        $View = $PsBoundParameters["ChangeAll"]
        $DatabaseInput = $PsBoundParameters["DatabaseInput"]
    }

    process
    {
        if($databaseInput)
        {
            return $databaseInput
        }
        else
        {
            return $False
        }
    }
}

正在运行:

MyFunction -ChangeAll
MyFunction -ChangeOne -DatabaseInput 3
MyFunction -ChangeOne 6

礼物:

False
3
6

编辑2

要创建更多参数,您需要向$RuntimeParameterDictionary

添加更多对象
function MyFunction
{
    [CmdletBinding(DefaultParameterSetName='View',PositionalBinding=$false)]
    Param(
        [Parameter(ParameterSetName='ChangeOne', Mandatory=$true, Position=0)]
        [Switch]$ChangeOne,

        [Parameter(ParameterSetName='ChangeAll', Mandatory=$true, Position=0)]
        [Switch]$ChangeAll,

        [Parameter(ParameterSetName='View', Mandatory=$false, Position=0)]
        [Switch]$View
    )

    DynamicParam
    {
        if($ChangeOne)
        {


            #Create a dictionary of parameters
            $RuntimeParameterDictionary = New-Object System.Management.Automation.RuntimeDefinedParameterDictionary

            ####Parameter 1
            $ParameterName = "databaseInput"

            #Array of values to validate against
            $ValidationArray = 1..9

            #Create parameter attributes
            $AttributeCollection = New-Object System.Collections.ObjectModel.Collection[System.Attribute]
            $ParameterAttribute = New-Object System.Management.Automation.ParameterAttribute
            $ParameterAttribute.Mandatory = $true
            $ParameterAttribute.Position = 1
            $AttributeCollection.Add($ParameterAttribute)

            #Add validation (omit if not needed)
            $ValidateSetAttribute = New-Object System.Management.Automation.ValidateSetAttribute($ValidationArray)
            $AttributeCollection.Add($ValidateSetAttribute)

            #Create the parameter
            $RuntimeParameter = New-Object System.Management.Automation.RuntimeDefinedParameter($ParameterName, [string], $AttributeCollection)

            #Add the parameter to the dictionary
            $RuntimeParameterDictionary.Add($ParameterName, $RuntimeParameter)

            ###Parameter 2
            $ParameterName = "Server"

            #Array of values to validate against
            $ValidationArray = "One","Two","Three"

            #Create parameter attributes
            $AttributeCollection = New-Object System.Collections.ObjectModel.Collection[System.Attribute]
            $ParameterAttribute = New-Object System.Management.Automation.ParameterAttribute
            $ParameterAttribute.Mandatory = $true
            $ParameterAttribute.Position = 2
            $AttributeCollection.Add($ParameterAttribute)

            #Add validation (omit if not needed)
            $ValidateSetAttribute = New-Object System.Management.Automation.ValidateSetAttribute($ValidationArray)
            $AttributeCollection.Add($ValidateSetAttribute)

            #Create the parameter
            $RuntimeParameter = New-Object System.Management.Automation.RuntimeDefinedParameter($ParameterName, [string], $AttributeCollection)

            #Add the parameter to the dictionary
            $RuntimeParameterDictionary.Add($ParameterName, $RuntimeParameter)

            #Return parameters
            Return $RuntimeParameterDictionary
        }
    }

    begin
    {
        $ChangeOne = $PsBoundParameters["ChangeOne"]
        $ChangeAll = $PsBoundParameters["ChangeAll"]
        $View = $PsBoundParameters["ChangeAll"]
        $DatabaseInput = $PsBoundParameters["DatabaseInput"]
        $Server = $PsBoundParameters["Server"]
    }

    process
    {
        if($databaseInput)
        {
            Return $DatabaseInput,$Server
        }
        else
        {
            Return $False
        }
    }
}

因此,运行以下命令:

MyFunction -ChangeOne -databaseInput 3 -Server Two
MyFunction -ChangeOne 7 Two

返回:

3
Two
7
Two

参考:https://blogs.technet.microsoft.com/poshchap/2017/09/01/scripting-tips-tricks-dynamic-parameters/

答案 1 :(得分:1)

您可以使用“参数集和验证”来完成此操作。

它看起来像这样:

[CmdletBinding(DefaultParameterSetName='View')]
Param(


    [Parameter(ParameterSetName='ChangeAll', Mandatory=$false)]
    [Switch]$ChangeAll,

    [Parameter(ParameterSetName='View', Mandatory=$false)]
    [Switch]$View,

    [Parameter(ParameterSetName='ChangeOne', Mandatory=$false)]
    [Switch]$ChangeOne,

    [Parameter(ParameterSetName='ChangeOne', Mandatory=$true)]
    [ValidateScript({![string]::IsNullOrEmpty($_.Trim())})]
    [string]$Database = ${if ($ChangeOne)`{Read-Host -Prompt "Database"`} else `{""`}}
)

或者,如果您知道希望看到的脚本,则验证可以如下所示:

[ValidateSet("Database1","Database2","Database3")]

验证将处理以确保输入是可接受的,该开关将驱动数据库参数的要求,并且如果您尝试传递不带-ChangeOne标志的数据库参数,它还将导致脚本中止并显示一个错误。