【问题标题】:Dynamic Parameters - with Dynamic ValidateSet动态参数 - 使用 Dynamic ValidateSet
【发布时间】:2018-04-13 14:54:57
【问题描述】:

我有一个脚本,我一直在编写它来提供对 SCCM 日志文件的解析。该脚本采用计算机名和磁盘位置来构建动态参数列表,然后将其呈现给用户以选择他们想要解析的日志文件。问题是我似乎无法让动态参数的 ValidateSet 部分为用户提供值。另外脚本在尝试调用函数时不会显示-log动态参数。

当你第一次运行它时,你不会看到我上面提到的动态参数 Log。如果你然后使用 -log 然后点击 tab 你会得到你所在目录中文件的命令完成器。这不是你所期望的;您会期望它会向您显示在动态参数执行期间收集的日志文件名称。

PSVersion 5.1.14409.1012

所以问题是如何让 PowerShell 向用户呈现正确的验证集项目?

如果您发出错误日志中的一项,您会得到正确的行为:

这是我用来实现这一点的两个函数:

function Get-CCMLog
{
    [CmdletBinding()]
    param([Parameter(Mandatory=$true,Position=0)]$ComputerName = '$env:computername', [Parameter(Mandatory=$true,Position=1)]$path = 'c:\windows\ccm\logs')
    DynamicParam
    {
        $ParameterName = 'Log'
        if($path.ToCharArray() -contains ':')
        {

            $FilePath = "\\$ComputerName\$($path -replace ':','$')"
            if(test-path $FilePath)
            {
                $logs = gci "$FilePath\*.log"
                $LogNames = $logs.basename

                $logAttribute = New-Object System.Management.Automation.ParameterAttribute
                $logAttribute.Position = 2
                $logAttribute.Mandatory = $true
                $logAttribute.HelpMessage = 'Pick A log to parse'                

                $logCollection = New-Object System.Collections.ObjectModel.Collection[System.Attribute]
                $logCollection.add($logAttribute)

                $logValidateSet = New-Object System.Management.Automation.ValidateSetAttribute($LogNames)
                $logCollection.add($logValidateSet)

                $logParam = New-Object System.Management.Automation.RuntimeDefinedParameter($ParameterName,[string],$logCollection)

                $logDictionary = New-Object System.Management.Automation.RuntimeDefinedParameterDictionary
                $logDictionary.Add($ParameterName,$logParam)
                return $logDictionary
            }
        }
    }
    begin {
        # Bind the parameter to a friendly variable
        $Log = $PsBoundParameters[$ParameterName]
    }

    process {
        # Your code goes here
        #dir -Path $Path
        $sb2 = "$((Get-ChildItem function:get-cmlog).scriptblock)`r`n"
        $sb1 = [scriptblock]::Create($sb2)
        $results = Invoke-Command -ComputerName $ComputerName -ScriptBlock $sb1 -ArgumentList "$path\$log.log"
        [PSCustomObject]@{"$($log)Log"=$results}
    }
}
function Get-CMLog
{
    param(
    [Parameter(Mandatory=$true,
               Position=0,
               ValueFromPipelineByPropertyName=$true)]
    [Alias("FullName")]
    $Path,
    $tail =10
    )
    PROCESS
    {

        if(($Path -isnot [array]) -and (test-path $Path -PathType Container) )
        {
            $Path = Get-ChildItem "$path\*.log"
        }

        foreach ($File in $Path)
        {
            if(!( test-path $file))
            {
                $Path +=(Get-ChildItem "$file*.log").fullname
            }
            $FileName = Split-Path -Path $File -Leaf
            if($tail)
            {
                $lines = Get-Content -Path $File -tail $tail 
            }
            else {
                $lines = get-cotnet -path $file
            }
            ForEach($l in $lines ){
                $l -match '\<\!\[LOG\[(?<Message>.*)?\]LOG\]\!\>\<time=\"(?<Time>.+)(?<TZAdjust>[+|-])(?<TZOffset>\d{2,3})\"\s+date=\"(?<Date>.+)?\"\s+component=\"(?<Component>.+)?\"\s+context="(?<Context>.*)?\"\s+type=\"(?<Type>\d)?\"\s+thread=\"(?<TID>\d+)?\"\s+file=\"(?<Reference>.+)?\"\>' | Out-Null
                    if($matches)
                    {
                        $UTCTime = [datetime]::ParseExact($("$($matches.date) $($matches.time)$($matches.TZAdjust)$($matches.TZOffset/60)"),"MM-dd-yyyy HH:mm:ss.fffz", $null, "AdjustToUniversal")
                        $LocalTime = [datetime]::ParseExact($("$($matches.date) $($matches.time)"),"MM-dd-yyyy HH:mm:ss.fff", $null)
                    }
                    [pscustomobject]@{
                        UTCTime = $UTCTime
                        LocalTime = $LocalTime
                        FileName = $FileName
                        Component = $matches.component
                        Context = $matches.context
                        Type = $matches.type
                        TID = $matches.TI
                        Reference = $matches.reference
                        Message = $matches.message
                }
            }
        }
    }
}

【问题讨论】:

  • 感谢您尝试使用 DynamicParam。我相信您需要将[ValidateSet()] 属性添加到-Log,其中包含您首先收集的文件范围,以便它在选项卡选择中可用。
  • 我认为这篇文章应该对你有所帮助。 blogs.technet.microsoft.com/pstips/2014/06/09/…
  • @persistent13 这是用作我的脚本的样板。谢谢提醒我链接在哪里。
  • 我无法复制您的问题。当我完成标签时,它显示了正确的选项-Log。抱歉,如果我无法复制,就很难排除故障。祝你好运

标签: powershell dynamic parameters


【解决方案1】:
【解决方案2】:

问题是你在 if 语句中的 scriptblock 中拥有所有动态逻辑,并且它仅在提供的路径包含分号(':')时处理参数添加。 您可以将其更改为:

if($path.ToCharArray() -contains ':') {
    $FilePath = "\\$ComputerName\$($path -replace ':','$')"
} else {
    $FilePath = $path
}

并从那里继续您的代码

【讨论】:

  • 感谢您的解决方案。这似乎工作得很好。
猜你喜欢
  • 2017-01-08
  • 2017-06-05
  • 2021-11-25
  • 2021-11-29
  • 2021-09-10
  • 1970-01-01
  • 2021-03-13
  • 2021-07-05
  • 2021-12-09
相关资源
最近更新 更多