2017-01-31 1 views
0

Powershell의 동적 매개 변수를 사용할 때 오류를 억제 할 수 있습니까?Powershell의 동적 매개 변수를 사용할 때 오류를 억제 할 수 있습니까?

특히 오류 존재 :

f foo 
Search-FrequentDirectory : Cannot validate argument on parameter 'dirSearch'. The argument "foo" does not belong to the set 
"bin,omega,ehiller,psmodules,deploy,gh.riotgames.com,build-go,vim74,cmder,dzr,vimfiles,src,openssh,git" specified by the ValidateSet attribute. Supply an argument 
that is in the set and then try the command again. 
At line:1 char:3 
+ f foo 
+ ~~~ 
    + CategoryInfo   : InvalidData: (:) [Search-FrequentDirectory], ParameterBindingValidationException 
    + FullyQualifiedErrorId : ParameterArgumentValidationError,Search-FrequentDirectory 

동적 매개 변수의 존재 :

DynamicParam { 
$dirSearch = new-object -Type System.Collections.ObjectModel.Collection[System.Attribute] 

# [parameter(mandatory=..., 
#  ... 
#)] 
$dirSearchParamAttribute = new-object System.Management.Automation.ParameterAttribute 
$dirSearchParamAttribute.Mandatory = $true 
$dirSearchParamAttribute.Position = 1 
$dirSearchParamAttribute.HelpMessage = "Enter one or more module names, separated by commas" 
$dirSearch.Add($dirSearchParamAttribute)  

# [ValidateSet[(...)] 
$dirPossibles = @() 

$historyFile = (Get-PSReadlineOption).HistorySavePath 
# directory Seperating character for the os; \ (escaped to \\) for windows (as C:\Users\);/for linux (as in /var/www/); 
# a catch all would be \\\/ ; but this invalidates the whitespace escape character that may be used mid-drectory. 
$dirSep = "\\" 
# Group[1] = Directory , Group[length-1] = lowest folder 
$regex = "^[[:blank:]]*cd ([a-zA-Z\~:]+([$dirSep][^$dirSep]+)*[$dirSep]([^$dirSep]+)[$dirSep]?)$" 
# original: ^[[:blank:]]*cd [a-zA-Z\~:\\\/]+([^\\\/]+[\\\/]?)*[\\\/]([^\\\/]+)[\/\\]?$ 
# test for historyFile existance 
if(-not (Test-Path $historyFile)){ 
    Write-Warning "File $historyFile not found, unable to load command history. Exiting."; 
    return 1; 
} 
$historyLines = Get-Content $historyFile 
# create a hash table, format of ;;; [directory path] = [lowest directory] 
$searchHistory = @{} 
# create a hash table for the count (number of times the command has been run) 
$searchCount = @{} 
ForEach ($line in $historyLines) { 
    if($line -match $regex){ 
     try { 
      # since the matches index can change, and a hashtable.count is not a valid way to find the index... 
      # I need this to figure out the highest integer index 
      $lowestDirectory = $matches[($matches.keys | sort -Descending | Select-Object -First 1)] 
      $fullPath = $matches[1] 
      if($searchHistory.keys -notcontains $matches[1]){ 
       $searchHistory.Add($matches[1],$lowestDirectory) 
      } 
      $searchCount[$fullPath] = 1 
     } catch { 
      $searchCount[$fullPath]++ 
     } 
    } 
} 
# this helps with hashtables 
# https://www.simple-talk.com/sysadmin/powershell/powershell-one-liners-collections-hashtables-arrays-and-strings/ 

$dirPossibles = ($searchHistory.values | Select -Unique) 

$modulesValidated_SetAttribute = New-Object -type System.Management.Automation.ValidateSetAttribute($dirPossibles) 
$dirSearch.Add($modulesValidated_SetAttribute) 

# Remaining boilerplate 
$dirSearchDefinition = new-object -Type System.Management.Automation.RuntimeDefinedParameter("dirSearch", [String[]], $dirSearch) 

$paramDictionary = new-object -Type System.Management.Automation.RuntimeDefinedParameterDictionary 
$paramDictionary.Add("dirSearch", $dirSearchDefinition) 

return $paramDictionary 
} 

기능 내가 설정 한 모든 일에있을 때 중대하다, 작동합니다. 내가 잘못했거나 어쨌든, 나는 스타일을 적용하고 싶지 않은 다소 불쾌한 (비 사용자 친화적 인 오류) 메시지를받습니다.

이 방법이 있습니까? 오류를 억제 하시겠습니까? 나는 try/catch을 시도했지만 아무 것도 시도하지 못했습니다. 그리고 나는 이것에 관해서 많은 것을 발견 할 수 없었습니다. 즉, 동적 매개 변수의 오류 억제입니다.

+0

충분하지 않습니다 문제를 이해하기 위해 제공된 코드,도 아니다. –

+0

코드의 전체가 필요하다고 생각하지 않았습니다. 문제의 원인이되는 것이 아니라 트리거하는 _valid 매개 변수 집합의 외부에있는 것입니다. 그러나 도움이 필요한 경우를 대비하여 DynamicParameter 코드 전체를 포함 시켰습니다. 나는 또한 오류를 추가했다. – ehiller

답변

0

나는 그것을 할 수있는 방법을 찾았지만 사용법을 정말로 권장하지는 못했으며 중복 된 코드의 단점이 있습니다. 어쩌면이 문제를 해결할 수있는 방법이있을 수 있지만, 수행 할 수 있다면 더 많이 수행했습니다.

코드가져 오기 - DynamicParamTestCustom.ps1

<# 
Reference: http://blog.enowsoftware.com/solutions-engine/bid/185867/Powershell-Upping-your-Parameter-Validation-Game-with-Dynamic-Parameters-Part-II 
#> 

[CmdletBinding()] 
param (
) 

DynamicParam { 
    function New-ValidationDynamicParam { 
     [CmdletBinding()] 
     [OutputType('System.Management.Automation.RuntimeDefinedParameter')] 
     param (
      [Parameter(Mandatory)] 
      [ValidateNotNullOrEmpty()] 
      [string]$Name, 

      [ValidateNotNullOrEmpty()] 
      [Parameter(Mandatory)] 
      [array]$ValidateSetOptions, 

      [Parameter()] 
      [switch]$Mandatory = $false, 

      [Parameter()] 
      [string]$ParameterSetName = '__AllParameterSets', 

      [Parameter()] 
      [switch]$ValueFromPipeline = $false, 

      [Parameter()] 
      [switch]$ValueFromPipelineByPropertyName = $false 
     ) 

     $AttribColl = New-Object System.Collections.ObjectModel.Collection[System.Attribute] 
     $ParamAttrib = New-Object System.Management.Automation.ParameterAttribute 
     $ParamAttrib.Mandatory = $Mandatory.IsPresent 
     $ParamAttrib.ParameterSetName = $ParameterSetName 
     $ParamAttrib.ValueFromPipeline = $ValueFromPipeline.IsPresent 
     $ParamAttrib.ValueFromPipelineByPropertyName = $ValueFromPipelineByPropertyName.IsPresent 
     $AttribColl.Add($ParamAttrib) 
     $AttribColl.Add((New-Object System.Management.Automation.ValidateSetAttribute($Param.ValidateSetOptions))) 
     $RuntimeParam = New-Object System.Management.Automation.RuntimeDefinedParameter($Param.Name, [string], $AttribColl) 

     $RuntimeParam 
    } 

    function Get-ValidValues 
    { 
     # get list of valid values 
     $validValues = @() 
     $validValues += 'a' 
     $validValues += 'b' 
     $validValues += 'c' 

     $validValues += $global:dynamic1Value 


     $validValues 
    } 

    # coerce the current passed value into our list, and we detect later 
    # to customize message 
    # the heart of this problem is getting the param from the Call Stack 
    # and stashing it away (a hack, but it IS a solution). 
    $line = (Get-PSCallStack | Select -First 1 | Select *).InvocationInfo.Line 
    # parse this for the command line arg 
    # TODO: make this more robust 
    $null = $line -match "-Dynamic1 (.*?)(\s+|$)" 
    $global:dynamic1Value = $Matches[1] 

    $ParamOptions = @(
     @{ 
     'Name' = 'Dynamic1'; 
     'Mandatory' = $true; 
     'ValidateSetOptions' = Get-ValidValues 
     } 
    ) 

    $RuntimeParamDic = New-Object System.Management.Automation.RuntimeDefinedParameterDictionary 
    foreach ($Param in $ParamOptions) 
    { 
     $RuntimeParam = New-ValidationDynamicParam @Param 
     $RuntimeParamDic.Add($Param.Name, $RuntimeParam) 
    } 

    return $RuntimeParamDic 
} 


begin 
{ 
    $PsBoundParameters.GetEnumerator() | foreach { New-Variable -Name $_.Key -Value $_.Value -ea 'SilentlyContinue'} 
} 

process 
{ 
    # not sure how else to write this because the function needs to be inside 
    # DynamicParam{} block for its usage, and here for 'process' usage. 
    function Get-ValidValuesReal 
    { 
     # get list of valid values 
     $validValues = @() 
     $validValues += 'a' 
     $validValues += 'b' 
     $validValues += 'c' 

     $validValues 
    } 

    function foo 
    { 
    } 

    Write-Output "global:dynamic1Value is: '$($global:dynamic1Value)'." 
    Write-Output "Dynamic1 is: '$($Dynamic1)'." 
    $realValues = Get-ValidValuesReal 
    if ($global:dynamic1Value -notin $realValues) 
    { 
     Write-Error "Hey, '$global:dynamic1Value' is not allowed." 
    } 
    else 
    { 
     Write-Output "Dynamic1 is: '$($Dynamic1)' and is cool." 
    } 

} 

end {} 

테스트 케이스

. \ GET-DynamicParamTestCustom.ps1 -Dynamic1의 t

. \ 가져 오기 - DynamicParamTestCustom.ps1 -Dynamic1 테스트

. \ GET-DynamicParamTestCustom.ps1 -Dynamic1 테스트

-Verbpse. \ GET-DynamicParamTestCustom.ps1 -Dynamic1 어떤 입력을 작동하거나 실패

관련 문제