Function Can';t调用函数中的管道属性。动力壳
所以我尝试创建一个“下载”函数,它使用管道对象属性来确定下载方法(sftp或http)。然后,为putty/winscp创建一个sftp脚本,或者卷曲http url。我对对象的定义如下: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 "
#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]我已经通过设置参数,如soParam([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