2

Can a parameter be passed as a parameter from one function to another?

Get-Version can retrieve the version from an installed package, an exe, or an MSI. I only allow one parameter to be used by using parameter sets.

function Get-Version{
    #returns version of either an installed file, or from an exe or msi path.
    param(
        [Parameter(ParameterSetName="installed")]
        [String]$SoftwareName,
        
        [Parameter(ParameterSetName="exepath")]
        [String]$ExePath,

        [Parameter(ParameterSetName="msipath")]
        [String]$MsiPath
    )
    switch ($PSCmdlet.ParameterSetName) {
        'installed' {
            $version = Get-Package | Where-Object {($_.Name -like $SoftwareName)} | Select-Object -ExpandProperty Version
        }
        'exepath' {
            $version = (Get-Item -path $ExePath).VersionInfo | Select-Object -ExpandProperty ProductVersion
        }
        'msipath' {
            try {
                $FullPath = (Resolve-Path $MsiPath).Path
                $windowsInstaller = New-Object -com WindowsInstaller.Installer

                $database = $windowsInstaller.GetType().InvokeMember(
                        "OpenDatabase", "InvokeMethod", $Null, 
                        $windowsInstaller, @($FullPath, 0)
                    )

                $q = "SELECT Value FROM Property WHERE Property = 'ProductVersion'"
                $View = $database.GetType().InvokeMember("OpenView", "InvokeMethod", $Null, $database, ($q))
                $View.GetType().InvokeMember("Execute", "InvokeMethod", $Null, $View, $Null)
                $record = $View.GetType().InvokeMember("Fetch", "InvokeMethod", $Null, $View, $Null)
                $productVersion = $record.GetType().InvokeMember("StringData", "GetProperty", $Null, $record, 1)

                $View.GetType().InvokeMember("Close", "InvokeMethod", $Null, $View, $Null)

                $version = $productVersion

            } catch {
                throw "Failed to get MSI file version the error was: {0}." -f $_
            }
        }
    }
    
    if($null -eq $version){
        #throw "Software not found"
        return $null
        return "SOFTWARE NOT FOUND"
    }elseif($version.GetTypeCode() -eq "String"){
        [System.Version]$version
    }else{
        #throw "More Than One Version Found"
        return $null
        return "TOO MANY SOFTWARE VERSIONS FOUND"
    }
}

Update-Software is not completely written yet, it calls Get-Version and I would like to be able to pass the MSIPath or ExePath to Get-Version without using an If statement, if possible.

function Update-Software {
    #checks installed and loaded software versions and returns true/false if it needs to be updated
    param (
        [Parameter(Mandatory=$True)]
        [String]$LocalSoftwareSearchString,
        
        [Parameter(Mandatory=$True)]
        [String]$LoadedSoftwarePath,

        [Parameter(Mandatory=$True)]
        [parameter?]$LoadedSoftwareParamaterType, ##This is where I dont know how to pass a parameter

        [Parameter(Mandatory=$True)]
        [String]$SoftwareDescription
    )


        $verSWInstalled = Get-Version -SoftwareName $LocalSoftwareSearchString
        $verSWLoaded = Get-Version -$LoadedSoftwareParamaterType $LoadedSoftwarePath


        if($verSWInstalled -gt $verSWLoaded){
            #return true
            #return message if upgrade needed
        }else{
            #return false
            #return message if upgrade not needed
        }
}

my ideal function call would look like for an EXE

Update-Software -LocalSoftwareSearchString Office365 -LoadedSoftwarePath D:\Office.exe -LoadedSoftwareParameterType ExePath

and this for an MSI

Update-Software -LocalSoftwareSearchString Office365 -LoadedSoftwarePath D:\Office.msi-LoadedSoftwareParameterType MsiPath

2
  • 1
    Call it using $PSBoundParameters the automatic variable was designed specifically for that use case Commented Oct 14, 2022 at 22:35
  • I think you need to change the concept, and think more OO (object oriented), meaning: rather than doing a Get-Version, do e.g. a Get-PackageDetails which returns an (ps)object (hashtable, or even a custom class) that includes properties like a version, path and possibly more information... Commented Oct 15, 2022 at 16:02

1 Answer 1

2

Define your parameter as follows, which limits the values you may pass to it to one of the values specified in the [ValidateSet()] attribute, which here correspond to the relevant parameter names of Get-Version:

      [Parameter(Mandatory=$True)]
      [ValidateSet('SoftwareName', 'ExePath', 'MsiPath')]
      [string] $LoadedSoftwareParameterType, 

Then pass this parameter's value as the parameter name through to Get-Version, and use the -LoadedSoftwarePath parameter's value as its value, via (hashtable-based) splatting:

$htArgs = @{ $LoadedSoftwareParameterType = $LoadedSoftwarePath }

# ...

$verSWLoaded = Get-Version @htArgs

To give a concrete example: The above makes Update-Software, when invoked with
-LoadedSoftwareParameterType ExePath -LoadedSoftwarePath c:\path\to\foo.exe, in effect internally call
Get-Version -ExePath c:\path\to\foo.exe

Sign up to request clarification or add additional context in comments.

2 Comments

Thank you so much, took me a while to understand this, but its very elegant! Thank you
Glad to hear it, @GeneParmesan; my pleasure.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.