我正在开发一个脚本,它将有效地花费时间和我提供的所有输入并将其吐出到现有的文本文件中。

我创建的参数是$ Input和$ logPath。 $ Input应该能够接受管道输入或使用“-Input”,而$ logPath参数则需要“-logpath”。

我不确定自己做错了什么,因为在ISE中使用自动完成功能时看不到那些开关。如果我尝试通过管道输入,则会得到:



如果我尝试坚持使用开关而不是管道输入,则可以使用一个,但是一旦输入一个,就不能使用第二个开关。

这是我的功能,感谢您的帮助:

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"
    }


}

最佳答案

您已为$Input$logPath指定了不同的参数集名称。这实际上意味着它们是互斥的,PowerShell将不允许您同时使用两者(这就是为什么它们未显示在ISE的自动完成功能中的原因)。由于在这种情况下您总是想同时使用两者,因此实际上根本不需要指定自定义参数集。

其他注意事项:

当我有您在这里时,我只想指出其他可能成为问题的事项:

您已将输入参数命名为$input,这是您不应该使用的,因为$input是PowerShell中的预定义/自动生成的变量(具体地说,$input是提供对当前管道的访问的枚举器对象),因此提供了一个函数参数相同的名称可能会导致脚本行为异常。

例如,如果您尝试像这样手动将值传递给参数:

Out-LogFile-输入“string1” -logPath test.txt

您的脚本将不会输出任何内容,因为$input引用了在这种情况下不包含任何内容的管道。我建议将$input重命名为$Message$InputObject,这与其他Out- cmdlet一致。

此块有两个问题:

试试{
详细写入正在检查现有的日志文件。
gi -Path $ logPath -ErrorVariable $ logPathError |空空
}
赶上{
抛出“退出!logPath不存在,您使用了-logpath参数吗?请参阅:$ logPathError”
}

首先,它将始终引发异常,因为您的Write-Verbose文本不在引号中,因此将单词“Checking”传递给Write-VerboseMessage参数,而不是将整个句子视为字符串,然后将“for”传递给接受字符串的下一个位置参数(当然不存在)。结果,您将收到一个“ParameterBindingException”,其内容大致如下:

Write-Verbose:找不到接受参数'for'的位置参数。

或者更确切地说,您会看到该异常,只是您已捕获了该异常,然后在catch块中引发了另一个异常,该异常表明脚本已退出并且logPath不存在。

但是,即使您修复了Write-Verbose上未加引号的字符串,如果Get-Item找不到$logPath,脚本也不会退出并且不会引发自定义异常。这是因为当Get-Item找不到项目时,它会抛出ItemNotFoundException

在PowerShell中,存在终止错误和非终止错误。 ItemNotFoundException。是终止错误。终止错误总是终止脚本(因此而得名),但是非终止错误的处理方式取决于当前 $ErrorActionPreference 。默认情况下,$ErrorActionPreference设置为“Continue”,这实际上意味着抛出非终止异常时,将显示错误并继续执行脚本;它不会被try-catch块捕获。

确定文件是否存在的更好方法是通过 Test-Path cmdlet:

如果(!(Test-Path -Path $ logPath))
{
抛出[System.IO.FileNotFoundException](“找不到logPath中指定的文件”)
}

这整个块都是不必要的(这是获取时间字符串的一种非常round回的方式):

#创建一个新的时间对象,并为其指定小时,分钟,秒,毫秒的属性。
试试{
详细写入“创建用于记录日志时间戳记的时间对象”
$ time =新对象PSObject -ErrorVariable $ timeError
$ time | Add-Member -MemberType NoteProperty -Name Hours -Value(Get-Date).Hour
$ time | Add-MemberType-MemberType NoteProperty -Name Minutes -Value(Get-Date).Minute
$ time | Add-Member-MemberType NoteProperty -Name Seconds -Value(获取日期)。第二
$ time | Add-MemberType-MemberType NoteProperty-Name毫秒-Value(Get-Date).Millisecond
#declare“currentTime”变量,用于在日志文件中放置时间戳。
[string] $ currentTime = $ time.Hours.ToString()+“:” + $ time.Minutes.ToString()+“:” + $ time.Seconds.ToString()+“:” + $ time.Milliseconds。 ToString()+“”

}

赶上{
抛出“无法创建PSObject:时间。请参阅:$ timeError”
}

获取特定格式的日期/时间字符串的最简单方法是在ToString()对象上调用 DateTime 方法。在括号中,我们可以指定standardcustom格式。 Get-Date返回一个DateTime对象,因此我们可以这样写:

$ currentTime =(Get-Date).ToString(“hh:mm:ss:fff”)+“”

除了对您和PowerShell的工作量较少之外,基本执行相同的操作。

最后,实际上没有任何理由将您的写操作包含在try-catch块中。如果写入操作失败(例如,由于文件为只读),那么这将是一个非终止错误,也不会被您的捕获捕获。

08-07 17:01