Powershell 给脚本传递参数 7


本文索引
[隐藏]

怎样将一个脚本稍作润色,让它能够根据用户的输入,处理并输出相应的结果,而不是只产生一成不变的输出。怎样将参数传递给脚本,这是本篇讨论的内容。

$args返回所有的参数

传递给一个函数或者一个脚本的参数都保存在$args变量中。可以先打开记事本,输入脚本:

Write-Host "Hello,$args"

保存后,通过控制台执行脚本:

PS E:> notepad myscript.ps1
PS E:> .MyScript.ps1
Hello,
PS E:> .MyScript.ps1 "Mosser Lee"
Hello,Mosser Lee

$args数组参数

默认情况下,传递给一个Powershell脚本的参数类型为数组,例如:

PS E:> .MyScript.ps1 My Website      Is        www.mossfly.com
Hello,My Website Is www.mossfly.com

上面的文本中包含多个连续的空格,可是当脚本把参数输出时却不存在连续的空格了。那是因为脚本会把文本根据白空格截断并转换成数组。如果不想文本被当成数组那就把它放在引号中。

PS E:> .MyScript.ps1 "My Website      Is        www.mossfly.com"
Hello,My Website      Is        www.mossfly.com

在$args中逐个访问参数

因为$args是一个数组,自然可以通过索引访问数组的每一个元素。可以将MyScript.sp1的内容改为:

For($i=0;$i -lt $args.Count; $i++)
{
	Write-Host "parameter $i : $($args[$i])"
}

然后在控制台测试:

PS E:> .MyScript.ps1 www moss fly com
parameter 0 : www
parameter 1 : moss
parameter 2 : fly
parameter 3 : com

在脚本中使用参数名

通过Powershell传递参数固然方便,但是如果用户不知道参数的传递顺序,也是很郁闷的,例如在Myscript.ps1中输入:
$args[0]-$args[1]
执行脚本发现参数的顺序不同,结果也不同:

PS E:> Get-Content .MyScript.ps1
$args[0]-$args[1]
PS E:> .MyScript.ps1 10 8
2
PS E:> .MyScript.ps1 8 10
-2

所以最好的方式给参数指定名称,输入以下的脚本:

param($Directory,$FileName)

"Directory= $Directory"
"FileName=$FileName"

其中param给参数指定名称。

执行脚本:

PS E:> .MyScript.ps1 -Directory $env:windir -FileName config.xml
Directory= C:windows
FileName=config.xml
PS E:> .MyScript.ps1 -FileName config.xml -Directory $env:windir
Directory= C:windows
FileName=config.xml

验证参数

给脚本的参数绑定数据类型,绑定帮助信息。一旦脚本缺少参数,或者输入的参数类型不正确,就提醒用户:
输入脚本:

param(
[string]$Name=$(throw "Parameter missing: -name Name") ,
[int]$Age=$(throw "Parameter missing: -age x as number")
)

"Name= $Name"
"Age=$Age"

执行脚本:

PS E:> .MyScript.ps1
Parameter missing: -name Name
所在位置 E:MyScript.ps1:2 字符: 22
+ [string]$Name=$(throw < <<<  "Parameter missing: -name Name") ,     + CategoryInfo          : OperationStopped: (Parameter missing: -name Name:String) [], Runtime    Exception     + FullyQualifiedErrorId : Parameter missing: -name Name PS E:> .MyScript.ps1 -Name mosser
Parameter missing: -age x as number
所在位置 E:MyScript.ps1:3 字符: 18
+ [int]$Age=$(throw < <<<  "Parameter missing: -age x as number")     + CategoryInfo          : OperationStopped: (Parameter missing: -age x as number:String) [], R    untimeException     + FullyQualifiedErrorId : Parameter missing: -age x as number PS E:> .MyScript.ps1 -Name mosser -Age abc
E:MyScript.ps1 : 无法处理对参数“Age”的参数转换。无法将值“abc”转换为类型“System.Int32”。错误:
“输入字符串的格式不正确。”
所在位置 行:1 字符: 33
+ .MyScript.ps1 -Name mosser -Age < <<<  abc     + CategoryInfo          : InvalidData: (:) [MyScript.ps1], ParameterBindin...mationException     + FullyQualifiedErrorId : ParameterArgumentTransformationError,MyScript.ps1 PS E:> .MyScript.ps1 -Name mosser -Age 100
Name= mosser
Age=100

变量的作用域

Powershell默认使用全局作用域global: ,但是在函数和脚本中分别使用函数作用域function:和脚本作用域script: 。
一旦脚本执行结束,存在于脚本作用域的变量也会消失。但是有一点,如果一个变量在脚本外定义,在脚本内没有定义,在脚本内使用时会把外面的变量引渡过来。

在脚本中输入:

$temp

执行脚本:

PS E:> .MyScript.ps1
PS E:> $temp="mosser lee"
PS E:> .MyScript.ps1
mosser lee

在脚本中尝试改变变量$temp,但是脚本内的变量不会影响脚本外的变量,输入脚本:

$temp="www.mossfly.com"
$temp

执行脚本:

PS E:> .MyScript.ps1
www.mossfly.com
PS E:> $temp
mosser lee
本文链接: http://www.pstips.net/powershell-pass-args-to-scripts.html
请尊重原作者和编辑的辛勤劳动,欢迎转载,并注明出处!

关于 Mooser Lee

我是一个Powershell的爱好者,创建了PowerShell中文博客,热衷于Powershell技术的搜集和分享。本站部分内容来源于互联网,不足之处敬请谅解,并欢迎您批评指正。


Leave a comment

电子邮件地址不会被公开。 必填项已用*标注

7 thoughts on “Powershell 给脚本传递参数

  • DJ

    我使用上面“验证参数”的代码,但是[string]$Name=$(throw “Parameter missing: -name Name”) ,这行却提示我The assignment expression is not valid. the input to an assignment operator must be an object that is able to accept assignments, suach as a variable or a property.
    我用我家里的电脑试了一下也是这样。

      • DJ

        #Get VMs on server
        Function GetVMSnapshots($ServerName, $ComputerName, $SnapshotName)
        {
        if($Script:IsWin10)
        {
        $VmSnapshots = Invoke-Command -ScriptBlock {Get-VM -ComputerName $ServerName | Get-VMSnapshot -Name $SnapshotName} -ComputerName $ServerName
        }
        else
        {
        $VmSnapshots = Get-VM -ComputerName $ServerName | Get-VMSnapshot -Name $SnapshotName
        }

        return $VmSnapshots
        }
        #Switch to a snapshot
        Function SwitchSnapshot($vm, $ServerName)
        {
        if($Script:IsWin10)
        {
        Invoke-Command -ScriptBlock {$vm | Resume-VM} -ComputerName $ServerName
        }
        else
        {
        $vm | Resume-VM
        }
        }
        #Will snapshot to start if its status is closed
        Function StartupVM($vm, $ServerName)
        {
        if($Script:IsWin10)
        {
        Invoke-Command -ScriptBlock {$vm | Start-VM} -ComputerName $ServerName
        }
        else
        {
        $vm | Start-VM
        }
        }
        #judge whether is Windows10, due to powershell version on Win10 is incompatible with servers’,
        #it needs to special processing
        Function IsWin10
        {
        $version = Get-WmiObject -Class Win32_OperatingSystem | Select-Object -ExcludeProperty Caption
        if($version.Version.Split(“.”)[0] -eq ’10’)
        {
        return $true
        }
        else
        {
        return $false
        }
        }

        param(
        [string] $servername = $(throw “Parameter of server name should be string”),
        #search for all of computers on the server that snapshot names named as $snapshotname if this parameter is null,
        #otherwise search for specify the snapshot of the computer on the server
        [string] $computername,
        [string] $snapshotname = $(throw “Parameter of snapshot name should be string”)
        )

        $Script:IsWin10 = IsWin10

        $vm = GetVMs -ServerName $servername -ComputerName $computername -SnapshotName $snapshotname
        SwitchSnapshot -vm $vm -ServerName $servername