3

I have recently begun experimenting with Binary PowerShell Programming in C#, and I am having some trouble with ParameterValidationAttributes, the ValidateScript Attribute mostly. Basically, i want to create a Param named "ComputerName" and validate the computer is online at that time. It was easy in PowerShell:

    [Parameter(ValueFromPipeLine = $true)]
    [ValidateScript({ if (Test-Connection -ComputerName $_ -Quiet -Count 1) { $true } else { throw "Unable to connect to $_." }})]
    [String]
    $ComputerName = $env:COMPUTERNAME,

But i cannot figure out how to replicate that in C#. the ValidateScript attribute takes a ScriptBlock object http://msdn.microsoft.com/en-us/library/system.management.automation.scriptblock(v=vs.85).aspx im just not sure how to create that in C#, and i cannot really find any examples.

[Parameter(ValueFromPipeline = true)]
[ValidateScript(//Code Here//)]
public string ComputerName { get; set; }

C# is very new to me, so i appologize if this is a dumb question. here is a link the ValidateScript Attribute Class: http://msdn.microsoft.com/en-us/library/system.management.automation.validatescriptattribute(v=vs.85).aspx

John Saunders
  • 160,644
  • 26
  • 247
  • 397
tomohulk
  • 592
  • 2
  • 9
  • 22

2 Answers2

7

It is not possible in C#, since .NET only allow compile time constants, typeof expressions and array creation expressions for attribute parameters and only constant available for reference types other then string is null. Instead you should derive from ValidateArgumentsAttribute and override Validate to perform validation:

class ValidateCustomAttribute:ValidateArgumentsAttribute {
    protected override void Validate(object arguments,EngineIntrinsics engineIntrinsics) {
        //Custom validation code
    }
}
user4003407
  • 21,204
  • 4
  • 50
  • 60
  • Thanks for the information, this maybe a little out of my conception of C#. So, after i create that Class can i just call it in the ValidateScript()? [ValidateScript({ValidateCustomAttribute.Validate(arg0, arg1)})] – tomohulk Jan 12 '15 at 19:04
  • @dotps1 You apply your custom attribute instead of `ValidateScriptAttribute`. – user4003407 Jan 12 '15 at 19:09
  • Thanks, i think i understand, so i can just throw an Exception if the computer cannot be contacted? – tomohulk Jan 12 '15 at 19:49
  • @dotps1 Yes, by throwing exception, you notify PowerShell that given argument does not pass validation. – user4003407 Jan 12 '15 at 19:54
  • ok, so here is what i have: `[Parameter()] [ValidateComputerName()] public string ComputerName {get; set;} // cmdlet here class ValidateComputerNameAttribute : ValidateArgumentsAttribute { protected override void Validate(object arguments, EngineIntrinsics engineIntrinsics) { try { Ping ping = new Ping(); ping.Send(arguments.ToString()); } catch { throw new SystemException("The specified system could not be contacted."); } } }` Just wanted to ask if that looks ok, im still amateur at C# – tomohulk Jan 12 '15 at 20:04
  • 1
    It looks ok for me, but you should be noted that `Ping.Send` does not throw if destination unreachable, so you should check returned value. – user4003407 Jan 12 '15 at 20:16
  • This is great @user4003407 but I'd love to see an example. – Craig.C Nov 26 '19 at 14:38
0

Just to expand on user4003407's answer above with a more complete example.

Derive a new validator from ValidateArgumentsAttribute and override Validate to perform validation. Validate is void so you really just get to throw exceptions in cases you choose.

Kevin Marquette has an excellent article but it's in powershell. Here is a c# example:

[Cmdlet(VerbsCommon.Get, "ExampleCommand")]
public class GetSolarLunarName : PSCmdlet
{   
    [Parameter(Position = 0, ValueFromPipeline = true, Mandatory = true)]
    [ValidateDateTime()]
    public DateTime UtcDateTime { get; set; }

    protected override void ProcessRecord()
    {

        var ExampleOutput = //Your code
        this.WriteObject(ExampleOutput);
        base.EndProcessing();
    }
}

class ValidateDateTime:ValidateArgumentsAttribute {
protected override void Validate(object arguments,EngineIntrinsics engineIntrinsics) {
    var date = (DateTime)arguments;
    if( date.Year < 1700 || date.Year > 2082){
        throw new ArgumentOutOfRangeException();
    }

}
Craig.C
  • 561
  • 4
  • 17