我正在编写一个脚本,它将有效地花费时间和我提供的任何输入并将其吐出到现有的文本文件中.
我创建的参数是$ Input和$ logPath.$ input应该能够采用管道输入或使用"-Input",而$ logPath参数需要"-logpath".
我不确定我做错了什么,因为在ISE中使用自动完成时我看不到那些开关.如果我尝试管道输入我得到:
"Out-LogFile:输入对象不能绑定到命令的任何参数,因为命令不接受管道输入或输入及其属性与任何接受管道输入的参数都不匹配.在行:1 char: 10"
如果我试图坚持开关而不是管道输入我可以使用一个,但一旦我输入一个我不能使用第二个开关.
这是我的功能,任何帮助表示赞赏:
function Global:Out-LogFile { #Planned function for outputting to a specified log file. <# .SYNOPSIS Adds to log files. .DESCRIPTION Updates a specified log file with a new line. The log file must already exist. See: Get-help New-LogFile .PARAMETER logPath Specifies a path for your new log (including file name). .EXAMPLE Get-ChildItem C:\ | Out-LogFile Piped input. #> [CmdletBinding()] param( [Parameter(Mandatory=$True, ValueFromPipeline=$True, ValueFromPipelineByPropertyName=$True, HelpMessage="input to append to logFile", ParameterSetName='Input')] [string[]]$Input, [Parameter(Mandatory=$True, HelpMessage="Please enter the path to your log file", ParameterSetName='logPath')] [string]$logPath ) #Check to see that $logpath physically exists as a log file. Try { Write-Verbose Checking for existing log file. gi -Path $logPath -ErrorVariable $logPathError | Out-Null } Catch { throw "quitting! logPath does not exist, did you use the -logpath parameter? see: $logPathError" } #Create new time object, give it properties of Hours, minutes, seconds, milliseconds. Try { Write-Verbose "Creating Time object for recording log timestamps" $time = New-Object PSObject -ErrorVariable $timeError $time | Add-Member -MemberType NoteProperty -Name Hours -Value (Get-Date).Hour $time | Add-Member -MemberType NoteProperty -Name Minutes -Value (Get-Date).Minute $time | Add-Member -MemberType NoteProperty -Name Seconds -Value (Get-Date).Second $time | Add-Member -MemberType NoteProperty -Name Milliseconds -Value (Get-Date).Millisecond #declare "currentTime" variable used to place timestamps in log files. [string]$currentTime = $time.Hours.ToString() + ":" + $time.Minutes.ToString() + ":" + $time.Seconds.ToString() + ":" + $time.Milliseconds.ToString() + " " } Catch { throw "Can't create PSObject: time. See: $timeError" } Try { #Append data to log file Write-Verbose "Writing line to log file" [string]$currentTime + [string]$Input >> $logPath } Catch { throw "Quitting! Can't write to log file" } }
Nacimota.. 5
您已为$Input
和指定了不同的参数集名称$logPath
.这实际上意味着它们是互斥的,PowerShell不允许您同时使用它们(这就是为什么它们没有出现在ISE的自动完成中).由于在这种情况下您总是希望同时使用两者,因此根本不需要指定自定义参数集.
虽然我有你在这里让我指出一些其他可能有问题的事情:
您已经命名了输入参数$input
,这是您不应该做的,因为它$input
是PowerShell中的预定义/自动生成的变量(具体来说,$input
是一个提供对当前管道的访问的枚举器对象),因此为函数参数赋予相同的名称可能会导致您的脚本以意想不到的方式运行.
例如,如果您尝试手动将值传递给参数,如下所示:
Out-LogFile -Input "string1" -logPath test.txt
您的脚本将不输出任何$input
内容,因为在这种情况下引用了没有任何内容的管道.我建议重命名$input
为$Message
或$InputObject
,这与其他Out-
cmdlet 一致.
这个块有几个问题:
Try { Write-Verbose Checking for existing log file. gi -Path $logPath -ErrorVariable $logPathError | Out-Null } Catch { throw "quitting! logPath does not exist, did you use the -logpath parameter? see: $logPathError" }
首先,它总是抛出一个异常,因为你的Write-Verbose
文本不是引号,所以而不是整个句子被视为一个字符串,单词"Checking"被传递给Write-Verbose
's Message
参数然后"for"传递给下一个位置接受字符串的参数(当然,不存在).因此,您将收到一个"ParameterBindingException",其中包含以下内容:
Write-Verbose : A positional parameter cannot be found that accepts argument 'for'.
或者更确切地说,您会看到该异常,除非您已捕获它,然后在catch块中抛出另一个异常,该异常表示脚本正在退出并且logPath不存在.
但即使您修复了未加引号的字符串Write-Verbose
,脚本也不会退出,如果Get-Item
找不到,则不会抛出自定义异常$logPath
.这是因为当Get-Item
找不到一个项目时,它会抛出一个ItemNotFoundException
.
在PowerShell中,存在终止错误和非终止错误.ItemNotFoundException
.是一个非终止错误.终止错误总是终止脚本(因此名称),但根据当前的不同,处理非终止错误$ErrorActionPreference
.默认情况下,$ErrorActionPreference
设置为"Continue",这实际上意味着当抛出非终止异常时,将显示错误并继续脚本; 它不会被try-catch块捕获.
确定文件是否存在的更好方法是通过Test-Path
cmdlet:
if (!(Test-Path -Path $logPath)) { throw [System.IO.FileNotFoundException]("Could not find the file specified in logPath") }
这整个块是不必要的(并且是获取时间字符串的一种非常迂回的方式):
#Create new time object, give it properties of Hours, minutes, seconds, milliseconds. Try { Write-Verbose "Creating Time object for recording log timestamps" $time = New-Object PSObject -ErrorVariable $timeError $time | Add-Member -MemberType NoteProperty -Name Hours -Value (Get-Date).Hour $time | Add-Member -MemberType NoteProperty -Name Minutes -Value (Get-Date).Minute $time | Add-Member -MemberType NoteProperty -Name Seconds -Value (Get-Date).Second $time | Add-Member -MemberType NoteProperty -Name Milliseconds -Value (Get-Date).Millisecond #declare "currentTime" variable used to place timestamps in log files. [string]$currentTime = $time.Hours.ToString() + ":" + $time.Minutes.ToString() + ":" + $time.Seconds.ToString() + ":" + $time.Milliseconds.ToString() + " " } Catch { throw "Can't create PSObject: time. See: $timeError" }
获取特定格式的日期/时间字符串的最简单方法是ToString()
在DateTime
对象上调用该方法.在括号中,我们可以指定标准或自定义格式.Get-Date
返回一个DateTime
对象,所以我们可以写:
$currentTime = (Get-Date).ToString("hh:mm:ss:fff") + " "
这基本上做同样的事情,除了它对你和PowerShell的工作都不那么重要.
最后,没有任何理由将您的写操作包含在try-catch块中.如果写入操作失败(例如,由于文件是只读的),这将是一个非终止错误,并且无论如何都不会被捕获.