Передавать параметр только в том случае, если указано значение

Фон

Я создал функцию-оболочку вокруг Write-EventLog, чтобы я мог легко вызывать ее, не беспокоясь о проверке и создании журнала/источника событий каждый раз. Просто добавляя параметр -Force, я хочу, чтобы он создавал журнал, если он не существует; если я не добавлю этот параметр, он должен вести себя как обычно (что снижает накладные расходы на несколько проверок, если они вызываются из кода, где я знаю, что этот журнал будет существовать).

Я скопировал список параметров, доступных для write-eventlog, чтобы у меня была полная функциональность, доступная для моей оболочки. Однако; если я не указываю значения некоторым из этих параметров (например, RawData), они по умолчанию равны нулю; затем я пытаюсь передать значение null для этого параметра; что отличается от того, чтобы не поставлять его. Я не хочу перечислять каждую возможную итерацию комбинаций параметров с проверкой того, были ли эти значения предоставлены перед вызовом соответствующей сигнатуры метода.

Вопрос

Есть ли способ передавать значения параметрам write-eventlog только там, где эти параметры были переданы write-eventlog2?

Код

cls
$myLog = 'Application'
$mySource = 'My PS Script'
$myEventId = 1 
[System.Diagnostics.EventLogEntryType]$myEntryType = [System.Diagnostics.EventLogEntryType]::Error 
$myMessage = 'This is a test message'

function Write-EventLog2
{
    [cmdletbinding()]
    param(  
        [Parameter(Position=0,Mandatory=$true,ValueFromPipeline=$true,ValueFromPipelineByPropertyName=$true)]
        [String]$LogName
        ,
        [Parameter(Position=1,Mandatory=$true,ValueFromPipeline=$true,ValueFromPipelineByPropertyName=$true)]
        [String]$Source
        ,
        [Parameter(Position=3,Mandatory=$true,ValueFromPipeline=$true,ValueFromPipelineByPropertyName=$true)]
        [Int32]$EventId
        ,
        [Parameter(Position=4,Mandatory=$false,ValueFromPipeline=$true,ValueFromPipelineByPropertyName=$true)]
        [System.Diagnostics.EventLogEntryType]$EntryType = [System.Diagnostics.EventLogEntryType]::Information
        ,
        [Parameter(Position=5,Mandatory=$false,ValueFromPipeline=$true,ValueFromPipelineByPropertyName=$true)]
        [String]$Message
        ,
        [Parameter(Position=6,Mandatory=$false,ValueFromPipeline=$false,ValueFromPipelineByPropertyName=$true)]
        [Int16]$Category = 1
        ,
        [Parameter(Position=7,Mandatory=$false,ValueFromPipeline=$false,ValueFromPipelineByPropertyName=$true)]
        [String]$ComputerName = $env:COMPUTERNAME
        ,
        [Parameter(Position=8,Mandatory=$false,ValueFromPipeline=$false,ValueFromPipelineByPropertyName=$true)]
        [Byte[]]$RawData
        ,
        [Parameter(Position=9,Mandatory=$false,ValueFromPipeline=$false,ValueFromPipelineByPropertyName=$true)]
        [switch]$Force 
    )

    begin
    {
        if($Force.IsPresent)
        {
            if (! ([System.Diagnostics.EventLog]::Exists($LogName) -and [System.Diagnostics.EventLog]::SourceExists($Source) )) 
            {
                New-EventLog -LogName $LogName -Source $Source 
            }
        }
    }
    process {
        Write-EventLog -LogName $LogName -Source $Source -EventId $EventId -EntryType $EntryType -Message $Message -Category $Category -ComputerName $ComputerName -RawData $RawData
    }
    #end{} #no ending actions required
}

Write-EventLog2 $myLog $mySource $myEventId $myEntryType $myMessage -Force

Ошибка

Write-EventLog : Cannot validate argument on parameter 'RawData'. 
The argument is null or empty. Provide an argument that is not 
null or empty, and then try the command again.
At line:51 char:167

person JohnLBevan    schedule 10.02.2015    source источник
comment
пс. Другим вариантом является Splatting, как показано здесь: not-it-exists-by-use" title="записать в журнал событий, не проверяя, существует ли он при использовании">codereview.stackexchange.com/questions/80154/   -  person JohnLBevan    schedule 30.07.2015
comment
Мой вопрос был очень похож на ваш. Посмотрите мой ответ stackoverflow.com/a/35773596/288393   -  person Tahir Hassan    schedule 04.03.2016


Ответы (2)


Я бы подумал о разбрызгивании для чего-то подобного, поскольку вы могли бы объяснить null / пустой, не меняя слишком много кода.

begin
    {
        if($Force.IsPresent)
        {
            if (! ([System.Diagnostics.EventLog]::Exists($LogName) -and [System.Diagnostics.EventLog]::SourceExists($Source) )) 
            {
                New-EventLog -LogName $LogName -Source $Source 
            }
        }

        if($rawdata){
            $rawdataparameter = @{
                RawData = $rawdata 
            }
        }

    }
    process {
        Write-EventLog -LogName $LogName -Source $Source -EventId $EventId -EntryType $EntryType -Message $Message -Category $Category -ComputerName $ComputerName @RawDataParameter
    }

Условно создайте небольшую хеш-таблицу, содержащую параметр по имени и значению. Используйте нотацию переменной со знаком at для обозначения команды Write-Log. На практике с Get-ChildItem, если таблица не содержит пар или имеет значение null, она игнорируется.

person Matt    schedule 10.02.2015
comment
Спасибо; хорошее решение, но я еще не отмечаю выбранный ответ, так как надеюсь, что появится более элегантное решение. . . - person JohnLBevan; 10.02.2015
comment
пс. это просто привело меня к открытию кое-чего - Remove-Variable; Я не понял, что несуществующая переменная действительна, но отличается от нуля. if($RawData -eq $null) {Remove-Variable RawData}; или if(!$RawData) {Remove-Variable RawData}; вроде работают хорошо. - person JohnLBevan; 10.02.2015

Спасибо Мэтту за то, что он помог мне понять, что неназначенная/объявленная переменная отличается от нуля, что привело меня к открытию Remove-Variable.

http://ss64.com/ps/remove-variable.html

Это изменяет переменную с простого значения $null на несуществующую; и, таким образом, не передается, даже если он указан как пройденный.

cls
$myLog = 'Application'
$mySource = 'My PS Script'
$myEventId = 1 
[System.Diagnostics.EventLogEntryType]$myEntryType = [System.Diagnostics.EventLogEntryType]::Error 
$myMessage = 'This is a test message'

function Write-EventLog2
{
    [cmdletbinding()]
    param(  
        [Parameter(Position=0,Mandatory=$true,ValueFromPipeline=$true,ValueFromPipelineByPropertyName=$true)]
        [String]$LogName
        ,
        [Parameter(Position=1,Mandatory=$true,ValueFromPipeline=$true,ValueFromPipelineByPropertyName=$true)]
        [String]$Source
        ,
        [Parameter(Position=3,Mandatory=$true,ValueFromPipeline=$true,ValueFromPipelineByPropertyName=$true)]
        [Int32]$EventId
        ,
        [Parameter(Position=4,Mandatory=$false,ValueFromPipeline=$true,ValueFromPipelineByPropertyName=$true)]
        [System.Diagnostics.EventLogEntryType]$EntryType
        ,
        [Parameter(Position=5,Mandatory=$false,ValueFromPipeline=$true,ValueFromPipelineByPropertyName=$true)]
        [String]$Message
        ,
        [Parameter(Position=6,Mandatory=$false,ValueFromPipeline=$false,ValueFromPipelineByPropertyName=$true)]
        [Int16]$Category 
        ,
        [Parameter(Position=7,Mandatory=$false,ValueFromPipeline=$false,ValueFromPipelineByPropertyName=$true)]
        [String]$ComputerName 
        ,
        [Parameter(Position=8,Mandatory=$false,ValueFromPipeline=$false,ValueFromPipelineByPropertyName=$true)]
        [Byte[]]$RawData
        ,
        [Parameter(Position=9,Mandatory=$false,ValueFromPipeline=$false,ValueFromPipelineByPropertyName=$true)]
        [switch]$Force 
    )

    begin
    {
        if($Force.IsPresent)
        {
            if (! ([System.Diagnostics.EventLog]::Exists($LogName) -and [System.Diagnostics.EventLog]::SourceExists($Source) )) 
            {
                New-EventLog -LogName $LogName -Source $Source 
            }
        }
    }
    process {
        if(!$EntryType) {Remove-Variable EntryType};
        if(!$Message) {Remove-Variable Message};
        if(!$Category) {Remove-Variable Category};
        if(!$ComputerName) {Remove-Variable ComputerName};
        if(!$RawData) {Remove-Variable RawData};
        Write-EventLog -LogName $LogName -Source $Source -EventId $EventId -EntryType $EntryType -Message $Message #-Category $Category -ComputerName $ComputerName -RawData $RawData
    }
    #end{} #no ending actions required
}

Write-EventLog2 $myLog $mySource $myEventId $myEntryType $myMessage -Force
person JohnLBevan    schedule 10.02.2015