Only pass parameter if value supplied

霸气de小男生 提交于 2019-12-13 15:13:53

问题


Background

I've created a wrapper function around Write-EventLog so that I can easily call it without having to concern myself with checking for & creating an event log/source each time. By simply adding a -Force parameter, I want it to create the log if it doesn't exist; if I don't add that parameter it should behave as normal (which reduces overhead of multiple checks if called from code where I know that log will exist).

I've copied the list of parameters available to write-eventlog such that I have the full functionality available to my wrapper. However; if I don't supply values to some of these parameters (e.g. RawData), they default to null; then I end up trying to pass null for this parameter; which is different to not supplying it. I don't want to have to list every possible iteration of parameter combinations with checks for whether those values were supplied before calling the appropriate method signature.

Question

Is there a way to only pass values to parameters of write-eventlog where those parameters had been passed to write-eventlog2?

Code

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

Error

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

回答1:


I would consider splatting for something like this as you could account for null / empty without changing too much of the code.

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
    }

Conditionally build a small hashtable that contains the parameter by name and the value. The use the at sign varialbe notation to splat the Write-Log command. In practice, with Get-ChildItem, if the table contains no pairs or is null it is ignored.




回答2:


Thanks to Matt for leading me to realise an unassigned/declared variable is different to null, which led me to the discovery of Remove-Variable.

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

This changes a variable from simply having the value $null to not existing; and thus not being passed even when listed as passed.

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


来源:https://stackoverflow.com/questions/28430620/only-pass-parameter-if-value-supplied

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!