Home > database >  Powershell Function with multiple parameters not accepting second pram
Powershell Function with multiple parameters not accepting second pram

Time:02-12

Trying to create a function that checks if you have a module installed along with that module being a minimum version. I have gotten it to work as a stand-alone check but when I try to make it function so that I don't have to have it repeated over and over when I have to check for multiple modules it fails the check for second input the version.

#Check if Module is avaiable
Function Module-Check {
#Set Pramatators
Param(
    [Parameter(
        Mandatory=$true,
        Position=0,
        HelpMessage="Enter the Modules name has show in Powershell",
        ParameterSetName="Module Name")]
    [string]
        $ModuleName,

    [Parameter(
        Mandatory=$true,
        Position=1,
        HelpMessage="Enter the Modules Major Version Required has show in Powershell",
        ParameterSetName="Major Version")]
    [string]
        $ModuleVersion
        )
        
        

$ModuleAvaiable = Get-Module -ListAvailable | Select Name,Version | Where-Object {$_.name -eq "$ModuleName"}

if ($ModuleAvaiable.Name.Count -eq '0') {
Write-Host -ForegroundColor Red "$ModuleName Module is not available on this computer"
$InstallModule=Read-Host "Would you like to install it now (Y)es or (N)o"
    Switch -Wildcard($InstallModule)
    {
        "Y*" {$Action= Write-host "Importing $ModuleName Module" 
           Install-Module -Name "$ModuleName"}
        "N*" {$Action= Write-host -ForegroundColor Yellow "Functions in the Powershell rely on This module and will not be able to function PS will now exit"
            break
            }
        Default {$Action= Write-Host "No input selected ending script"
                break}
        }
    return $Action
}
else {
Write-Host "$ModuleName" $ModuleAvaiable.Version"is Avaiable on this computer"
$RequiredVersion = ($ModuleAvaiable.Version.Major -ge $ModuleVersion)
    if ($RequiredVersion = $true) {
    }
else {
    Write-Host -ForegroundColor Yellow "$ModuleName Module Version installed does not meet the required mimium version (version $ModuleVersion.X)"
    $UpdateModule=Read-Host "Update the Module version now (Y)es or (N)o"
        switch -Wildcard ($UpdateModule)
        {
        "Y*" {$Action2= Write-host "Update $ModuleName Module" 
            update-Module -Name "$ModuleName"}
        "N*" {$Action2= Write-host -ForegroundColor Yellow "Functions in the Powershell rely on this module and may not function properly with a lower version installed"
            
            }
        Default {$Action2= Write-Host "No input selected updating ALL Modules"
                foreach ($module in Get-InstalledModule) {
                    Get-InstalledModule $module.Name -AllVersions | 
                    Where-Object Version -ne $module.Version | 
                    Uninstall-Module
                                                            }
                }
        }
    Return $Action2

     } 
  }
}

CodePudding user response:

Maybe I am misreading your question but, here goes... Since you have defined your parameters with different parameter set names, they basically aren't supposed to be used together.

For instance, this simple gibberish function should demonstrate the phenomenon.

function Test-Something
{
    Param
    (
        [Parameter(ParameterSetName="Set1")][int]$P1,
        [Parameter(ParameterSetName="Set2")][int]$P2,
        [Parameter(ParameterSetName="Set1")][int]$P3
    )
}

When running for example Test-Something -P1 1 you would be able to also use -P3, but running the same function with -P2 then -P1 and -P3 should not be exposed.

Running Get-Command Test-Something -Syntax, in this case should expose two separate alternatives, and the same should be true for your function where running Get-Command Module-Check -Syntax would expose

Module-Check [-ModuleName] <string> [<CommonParameters>]
Module-Check [-ModuleVersion] <string> [<CommonParameters>]

Removing (or renaming them with the exact same name) ParameterSetName="Module Name" and ParameterSetName="Major Version" should fix this problem

CodePudding user response:

You are not understanding ParameterSetName and Mandatory. The code below is from one of over a dozen functions I've been working on.

It allows for:

  1. $KeyPath by itself - Parameter set KHK
  2. $KeyPath with only one of the six data types - Parameter sets BVE, DVE, EVE, MVE, QVE, and SVE
  3. $Keypath with $ValueName and only one of the six data types - Parameter sets BVN, DVN, EVN, MVN, QVN, and SVN

Near the top you can see that 'KHK' is the default parameter set. If you look at $KeyPath, it is mandatory for all parameter sets, so specifying only $KeyPath results in 'KHK'. But if you look at $ValueName, it is mandatory for all the parameter sets that end in the letters 'VN', this also means you will need to include a data type parameter with $ValueName. The VN stands for $ValueName.

In my scheme I'm using the first letter as the type of data that will be written to the registry. And you can see below that each data type has those parameter sets that match. Binary requires 'B', PSInt/$RegDWord requires 'D', and so on.

The goal is to make it mandatory for certain parameters to be in the same set, while others are excluded. What may not be obvious in this code is the fact that specifying only $KeyPath and $RegDWord will result in 'DVE' since $ValueName wasn't included, but adding $ValueName to the parameters results in 'DVN'. But what should be hopefully be obvious is that once $RegDWord is provided, no other data type parameter is allowed since they do not share any of the same parameter sets.

Also, at the bottom of the code is included a way to break the resulting ParametSetName into two, so it can be known if $ValueName was provided and what data type was provided.

Sorry if this code is a bit much to chew on for someone still new to parameter sets, but it is one of the best real world examples I know of for showing what can be done. I'm sure there are examples out there, but I didn't find them when I was trying to figure this out myself.

One last thing, what isn't shown in the code is that you can have a parameter that is part of a parameter set, but not mandatory. This means that this "parameter set" does not require that parameter. Think of it this way, you cannot have a certain "parameter set" become active UNLESS all of its mandatory parameters are provided. I might add, there is a limit to how many parameter sets you can have, I think it is around two and half to three times what is in this example - yeah, I hit that wall!

Function Set-Reg {
    [CmdletBinding(DefaultParameterSetName = 'KHK')]
    Param(
        [Parameter(Mandatory = $true, Position = 0)]
        [string]$KeyPath,

        [Parameter(Mandatory, ParameterSetName = 'BVN')]
        [Parameter(Mandatory, ParameterSetName = 'DVN')]
        [Parameter(Mandatory, ParameterSetName = 'EVN')]
        [Parameter(Mandatory, ParameterSetName = 'MVN')]
        [Parameter(Mandatory, ParameterSetName = 'QVN')]
        [Parameter(Mandatory, ParameterSetName = 'SVN')]
        [AllowEmptyString()]
        [Alias("v")]
        [string]$ValueName,

        [Parameter(Mandatory, ParameterSetName = 'BVE')]
        [Parameter(Mandatory, ParameterSetName = 'BVN')]
        [Alias("PSBytes")]
        [byte[]]$RegBinary,
        [Parameter(Mandatory, ParameterSetName = 'DVE')]
        [Parameter(Mandatory, ParameterSetName = 'DVN')]
        [Alias("PSInt")]
        [int]$RegDWord,
        [Parameter(Mandatory, ParameterSetName = 'EVE')]
        [Parameter(Mandatory, ParameterSetName = 'EVN')]
        [AllowEmptyString()]
        [Alias("PSEString")]
        [string]$RegExpandString,
        [Parameter(Mandatory, ParameterSetName = 'MVE')]
        [Parameter(Mandatory, ParameterSetName = 'MVN')]
        [Alias("PSStrings")]
        [string[]]$RegMultiString,
        [Parameter(Mandatory, ParameterSetName = 'QVE')]
        [Parameter(Mandatory, ParameterSetName = 'QVN')]
        [Alias("PSLong")]
        [long]$RegQWord,
        [Parameter(Mandatory, ParameterSetName = 'SVE')]
        [Parameter(Mandatory, ParameterSetName = 'SVN')]
        [AllowEmptyString()]
        [Alias("PSString")]
        [string]$RegString,
        [switch]$x32
    )
    # ve: default string "(value not set)"
    $SetNames = [PSCustomObject]@{
        Type = $PsCmdlet.ParameterSetName.Substring(0, 1)
        Mode = $PsCmdlet.ParameterSetName.Substring(1, 2)
    }
  • Related