Function Can';t调用函数中的管道属性。动力壳

Function Can';t调用函数中的管道属性。动力壳,function,powershell,object,if-statement,pipeline,Function,Powershell,Object,If Statement,Pipeline,所以我尝试创建一个“下载”函数,它使用管道对象属性来确定下载方法(sftp或http)。然后,为putty/winscp创建一个sftp脚本,或者卷曲http url。我对对象的定义如下: #WinSCP $winscp = new-object psobject $winscp | add-member noteproperty name "WinSCP" $winscp | add-member noteproperty dltype "

所以我尝试创建一个“下载”函数,它使用管道对象属性来确定下载方法(sftp或http)。然后,为putty/winscp创建一个sftp脚本,或者卷曲http url。我对对象的定义如下:

#WinSCP
$winscp = new-object psobject            
$winscp | add-member noteproperty name "WinSCP"
$winscp | add-member noteproperty dltype "http"
$winscp | add-member noteproperty file "winscp.exe"
$winscp | add-member noteproperty url "https://cdn.winscp.net/files/WinSCP-5.17.8-Setup.exe"
$winscp | add-member noteproperty path "$env:ProgramFiles(x86)\WinSCP"
$winscp | add-member noteproperty install 'msiexec /i "$DataPath\$winscp.file" /quiet /norestart'

#Database
$db = new-object psobject            
$db | add-member noteproperty name "Client Database"
$db | add-member noteproperty dltype "sftp"
$db | add-member noteproperty file "database_"
$db | add-member noteproperty ver "check"
$db | add-member noteproperty ext ".csv"
$db | add-member noteproperty dir "db"

#DatabaseVersion
$db_ver = new-object psobject            
$db_ver | add-member noteproperty name "Database Version File"
$db_ver | add-member noteproperty dltype "sftp"
$db_ver | add-member noteproperty file "current_version.txt"
$db_ver | add-member noteproperty dir "db"
目前我对函数中的$Input变量有问题。它只能使用一次,不能转换为if语句。因为它包含一个具有多个属性的对象,所以我认为它首先需要转换为函数中的一个新对象。我是powershell的新手,还没有找到这样做的方法。以下是我制作并尝试使用的函数:

function Download () {

    #HTTP Download Method
    if ($input.dltype -eq "http") {
        curl $input.url -O $DataPath\$input.file
        #HTTP Success or Error
        $curlResult = $LastExitCode
        if ($curlResult -eq 0)
        {
          Write-Host "Successfully downloaded $input.name"
        }
        else
        {
          Write-Host "Error downloading $input.name"
        }
        pause
}

    #SFTP Download Method
    if ($input.dltype -eq "sftp") {
        sftpPassCheck
        #Detect if version required
        if ($input.ver = "check") {
        #Download the objects version file
        "$+$Input+_ver" | Download
        #Update the object's ver property
        $input.ver = [IO.File]::ReadAllText("$DataPath\current_version.txt")
        #Build the new filename
        $input.file = "$input.file"+"$input.ver"+"$input.ext"
        #Delete the version file
        Remove-Item "$DataPath\current_version.txt"
        }
        & "C:\Program Files (x86)\WinSCP\WinSCP.com" `
         /log="$DataPath\SFTP.log" /ini=nul `
         /command `
            "open sftp://ftpconnector:$script:sftp_pass@$input.ip/ -hostkey=`"`"ssh-ed25519 255 SETvoRlAT0/eJJpRhRRpBO5vLfrhm5L1mRrMkOiPS70=`"`" -rawsettings ProxyPort=0" `
            "cd /$input.dir" `
            "lcd $DataPath" `
            "get $input.file" `
            "exit"
        #SFTP Success or Error
        $winscpResult = $LastExitCode
        if ($winscpResult -eq 0)
        {
          Write-Host "Successfully downloaded $input.name"
        }
        else
        {
          Write-Host "Error downloading $input.name"
        }
    }
}
我可能遗漏了一些简单的东西,但在这一点上我一无所知。Oh用法应为:

WinSCP | download

将管道输入绑定到函数参数的正确方法是声明一个高级函数-请参阅本答案底部部分的实现

但是,在简单情况下,
过滤器将起作用,它是一种函数的简化形式,隐式地将管道输入绑定到,并为每个输入对象调用:

filter Download {
  if ($_.dltype -eq "http") { 
    # ...
  }
}
,在简单(非高级)
函数中,它是接收到的所有管道输入的枚举器,因此必须循环

也就是说,以下简单
函数
与上述
过滤器
等效:

function Download {
  # Explicit looping over $input is required.
  foreach ($obj in $input) {
    if ($obj.dltype -eq "http") { 
      # ...
    }
  }
}

如果您确实希望将其转换为高级功能(请注意,我已更改名称以符合PowerShell的动词-名词命名约定):

-
$input
实际上并不打算直接使用,您最好明确声明输入参数

除了该答案中显示的
$InputObject
模式外,还可以按名称将输入对象属性值绑定到参数:

函数下载
{
param(
[参数(ValueFromPipelineByPropertyName=$true)]
[别名('dltype')]
[string]$Protocol='http'
) 
过程{
写入主机“协议选择:$protocol”
}
}
请注意,尽管此参数的名称为
$Protocol
,但
[Alias('dltype')]
属性将确保输入对象上的
dltype
属性的值已绑定

其效果是:

PS ~> $WinSCP,$db |Download
Choice of protocol: http
Choice of protocol: sftp
对任何必需的输入参数重复此模式-声明映射到属性名称的命名参数(如果需要),您可能会得到如下结果:

function Download
{
    [CmdletBinding()]
    param(
        [Parameter(ValueFromPipelineByPropertyName = $true)]
        [ValidateSet('sftp', 'http')]
        [Alias('dltype')]
        [string]$Protocol,

        [Parameter(ValueFromPipelineByPropertyName = $true)]
        [Alias('dir')]
        [string]$Path = $PWD,

        [Parameter(Mandatory = $true, ValueFromPipelineByPropertyName = $true)]
        [Alias('url','file')]
        [string]$Uri
    )

    process {
        Write-Host "Downloading $Uri to $Path over $Protocol"
    }
}
现在您可以执行以下操作:

PS ~> $WinSCP,$db |Download
Downloading https://cdn.winscp.net/files/WinSCP-5.17.8-Setup.exe to C:\Program Files(x86)\WinSCP over http
Downloading database_ to db over sftp
我们不再依赖于直接访问
$input
$InputObject
$\uucode>,既美观又干净


有关参数声明的详细信息,请参阅。

您一定要通读:)
$Input
是一个保留的自动变量。请勿将其用作只读以外的任何其他用途。。。[grin]我已经通过设置参数,如so
Param([Parameter(Mandatory=$true,ValueFromPiepline=$true)][String[]]$name,
但对于类型“System.Management.Automation.CmdletBindingAttribute”,找不到属性“ValueFromPiepline”。位于C:\Users\Chris\Desktop\catatool.ps1:95 char:5+ValueFromPiepline=$true)]+~~~~~~~~~~~~~~~~~~~~~+CategoryInfo:InvalidOperation:(ValueFromPiepline=$true:NamedAttributeArgumentAst)[],RuntimeException on+FullyQualifiedErrorId:PropertyNotFoundForType
@ChristianScottLePere:您的尝试中有一个输入错误:
ValueFromPiepline
->
ValueFromPipeline
;我的答案现在显示了一个示例。还要注意,
$input.ver=“check”
应为
$input.ver-eq“check”
,否则将执行赋值。
PS ~> $WinSCP,$db |Download
Downloading https://cdn.winscp.net/files/WinSCP-5.17.8-Setup.exe to C:\Program Files(x86)\WinSCP over http
Downloading database_ to db over sftp