Author Posts

October 12, 2015 at 4:01 am

Is this the correct usage of a switch command ?

So below is part of testing, but the full script will evaluate if the input is either a UUID number or a MACaddress, then pass the result to import a machine with the number passed. The command requires either a -SmBiosGuid or -MACAddress.

$Identifer = "F8:16:54:C1:83:33"

    $UUID = "^\w{8}\-\w{4}\-\w{4}\-\w{4}\-\w{12}$"
    $MAC = "^\w{2}\:\w{2}\:\w{2}\:\w{2}\:\w{2}\:\w{2}$"
    
    Switch ($Identifer) {
    {$Identifer -match $UUID} { "UUID" }
    {$Identifer -match $MAC} { "MACAddress" }
    }

October 12, 2015 at 5:35 am

I'm thinking an ElseIf is the better solution :


function add-machine
{
    [CmdletBinding()]
    Param
    (
        # Param1 help description
        [Parameter(Mandatory=$true,
                   ValueFromPipeline=$True,
                   HelpMessage="Computer Name then either MACAddress or UUID (SmBiosGuid)")]
        [string[]]$ComputerName,
        [string[]]$Identifer,
        
        [string]$ErrorLog = 'c:\temp\AddDeviceError.txt'
    )         
    
    Begin
    {
#Import Configuration Manager module
    $ModulePath = $env:SMS_ADMIN_UI_PATH.Replace("i386","ConfigurationManager.psd1")
    Import-Module $ModulePath
    }
    Process
    {
    [regex]$MAC = "^\w{2}\:\w{2}\:\w{2}\:\w{2}\:\w{2}\:\w{2}$"
        [regex]$UUID = "^\w{8}\-\w{4}\-\w{4}\-\w{4}\-\w{12}$"

        if ($Identifier -match $MAC) 
            { Import-CMComputerInformation -CollectionName "All Systems" -ComputerName $ComputerName -MacAddress $Identifier }
        elseif ($Identifier -match $UUID)
            { Import-CMComputerInformation -CollectionName "All Systems" -ComputerName $ComputerName -SmBiosGuid $Identifier }
        else
            {Write-Warning "Not a valid MAC Address or SmBiosGuid"}
    }

     #Import-CMComputerInformation -CollectionName "All Systems" -ComputerName $ComputerName -SmBiosGuid 
    }
    End
    {
    }

October 12, 2015 at 5:46 am

Your example is basically attempting to match and if it matches then you can identify the identifier passed. See the example code below for switch and validateset implementations:

function Test-ValidateSet {
    param (
        [ValidateSet("MAC", "UUID")]
        [string]$IdentifierType,
        [string]$Identifier
        
    )
    
    switch ($IdentityType) {
        "MAC" {$Pattern = "^\w{2}\:\w{2}\:\w{2}\:\w{2}\:\w{2}\:\w{2}$"}
        "UUID"{ $Pattern = "^\w{8}\-\w{4}\-\w{4}\-\w{4}\-\w{12}$" }
    }
    
    if ($Identifier -match $Pattern) {
        
    }
    else {
        "Bad identifier"   
    }
}



function Test-Switch {
    param (
        [string]$Identifier,
        [switch]$IsUUID
        
    )
    #Default pattern is MAC, so if you wanted to pass a UUID you'd have to specify the IsUUID switch
    $Pattern = "^\w{2}\:\w{2}\:\w{2}\:\w{2}\:\w{2}\:\w{2}$" }
    if ($IsUUID) {$Pattern = "^\w{8}\-\w{4}\-\w{4}\-\w{4}\-\w{12}$" }
        
    if ($Identifier -match $Pattern) {
        
    }
    else {
        "Bad identifier"
    }
}

October 12, 2015 at 5:51 am

Rob, brilliant. Funny, now i look at what you have done looks logical. Not used the ValidateSet yet, useful to know. Learn't a bit more today, so many thanks.

October 12, 2015 at 5:56 am

Rob, with the test-validate, do i pass the MAC or UUID to the Identifer ?

October 12, 2015 at 2:59 pm

Graham, your way works, but you would typically structure it something like this.

$Identifer = "F8:16:54:C1:83:33"
#$Identifer = "d75e6376-7133-11e5-9d70-feff819cdc9f"

    $UUID = "^\w{8}\-\w{4}\-\w{4}\-\w{4}\-\w{12}$"
    $MAC = "^\w{2}\:\w{2}\:\w{2}\:\w{2}\:\w{2}\:\w{2}$"
    
    Switch -regex ($Identifer) {
        $UUID { "UUID" }
        $MAC { "MACAddress" }
    }

or if you did not want to use variables

$Identifer = "F8:16:54:C1:83:33"
#$Identifer = "d75e6376-7133-11e5-9d70-feff819cdc9f"
    
    Switch -regex ($Identifer) {
        "^\w{8}\-\w{4}\-\w{4}\-\w{4}\-\w{12}$" { "UUID" }
        "^\w{2}\:\w{2}\:\w{2}\:\w{2}\:\w{2}\:\w{2}$" { "MACAddress" }
    }

October 12, 2015 at 3:49 pm

Great examples above. Here's how I'd handle it.

Function Test-Function {
        
    [CmdletBinding(SupportsShouldProcess=$true,
                        ConfirmImpact='Medium')]
    Param (
        # Specifies the UUID or MAC Address
        [Parameter(Mandatory=$true)]
        [System.String]
        [ValidateScript({($_ -match "^\w{2}\:\w{2}\:\w{2}\:\w{2}\:\w{2}\:\w{2}$") -or ($_ -match "^\w{8}\-\w{4}\-\w{4}\-\w{4}\-\w{12}$")})]
        [System.String]
        $Identifer

    )

    If ($Identifer -match "^\w{2}\:\w{2}\:\w{2}\:\w{2}\:\w{2}\:\w{2}$") {
        # MAC Address was entered
        "MAC Address"
    }
    Else {
        # UUID was entered
        "UUID"
    }
    
}

Then some test code

Test-Function -Identifer 20:58:9D:17:EF:52
Test-Function -Identifer f6f94322-7138-11e5-9d70-feff819cdc9f
Test-Function -Identifer Nonsense

October 12, 2015 at 11:08 pm

Curtis and Scriptimus thank, both excellent solution. Fascinated by yours Scriptimus. Thank you !

October 12, 2015 at 11:49 pm

My "Catch" doesn't seem to work if the regex is not met...

Function Test-Function {
        
    [CmdletBinding(SupportsShouldProcess=$true,
                        ConfirmImpact='Medium')]
    Param (
        # Specifies the UUID or MAC Address
        [Parameter(Mandatory=$true)]
        [System.String]
        [ValidateScript({($_ -match "^\w{2}\:\w{2}\:\w{2}\:\w{2}\:\w{2}\:\w{2}$") -or ($_ -match "^\w{8}\-\w{4}\-\w{4}\-\w{4}\-\w{12}$")})]
        [System.String]
        $Identifer

    )

try {
    If ($Identifer -match "^\w{2}\:\w{2}\:\w{2}\:\w{2}\:\w{2}\:\w{2}$") {
        # MAC Address was entered
        write-output "MAC Address" -ea STOP
    }
    Else {
        # UUID was entered
        write-output "UUID" -ea STOP
    }
}
catch {
    {
    #No Return
    write-warning $($_.Exception.Message)
    }
  }
}

October 13, 2015 at 12:22 am

The design here is that the Validate script will not allow the function to get past the parameter section if the regex is not matched.

As for the try/catch. This would typically go inside the If/Else scriptblocks but only if you wanted to handle something that could catastrophically fail.

In this situation you're not doing anything except returning a string. The If/Else is sufficient.

To eliminate confusion further instead of write-output "UUID" as you used above, in the final code you could use
return 'UUID'

October 14, 2015 at 10:47 pm

Scriptimus Prime, why you do test for $Identifier twice ?
your code
"# UUID was entered
write-output "UUID" -ea STOP"

with this design can't be executed at all because the ValidateScript disallow it

October 15, 2015 at 12:01 am

Yes Max, I gave that some thought.

The validate script seemed to be the more PowerShell way to start the script.

However, from then I couldn't find a way to identify what was passed without testing again.

if the reduction of iterations was an objective, then perhaps it would be better to use switch or If, ElseIf, Else.