I'm new to PowerShell, and I'm having trouble with parameter sets. I've created a function that will retrieve memory info from a computer. I have the function working properly, except for the parameters sets. Here's the syntax I want to support:
#Run without parameters for memory usage on localhost: Get-MemoryUsage #Get memory usage on remote system: Get-MemoryUsage [-ComputerName] <String> #Examples: # Get-MemoryUsage -ComputerName mydc01 # Get-MemoryUsage mydc01 # "mydc01", "mydc02" | Get-MemoryUsage #Get memory usage on remote system running on Hyper-V host, where "name" is the name of the virtual machine in Hyper-V manager: Get-MemoryUsage [-ComputerName] <String> [-HostName] <String> [-Name] <String> #Examples: # Get-MemoryUsage -ComputerName mydc01 -HostName hvsvr -Name TheDC # Get-MemoryUsage mydc01 hvsvr TheDC #Get memory usage on remote system running on Hyper-V host, where "ID" is the GUID of the virtual machine: Get-MemoryUsage [-ComputerName] <String> [-HostName] <String> [-ID] <GUID> #Examples: # Get-MemoryUsage -ComputerName mydc01 -HostName hvsvr -ID 837b8cbc-b89c-4070-bf65-4b674bb380e4 # Get-MemoryUsage mydc01 hvsvr [GUID]837b8cbc-b89c-4070-bf65-4b674bb380e4 #Lastly, I want to be able to pipeline in a [Microsoft.HyperV.PowerShell.VirtualMachine] object like so: Get-VM -ComputerName hvsvr -Name TheDC | Get-MemoryUsage -Computername mydc01 $vm = Get-VM -Name TheDC ; Get-MemoryUsage mydc01 $vm
To summarize syntax:
- You must always specify the computer name, unless you want to target the local computer
- If targeting a Hyper-V virtual machine, you must also specify one of the following:
- 1. The Hyper-V server and virtual machine name
- 2. The Hyper-V server and virtual machine GUID
- 3. A [Microsoft.HyperV.PowerShell.VirtualMachine] object
Here's the function declaration:
function Get-MemoryUsage {
[CmdletBinding()]
param (
[Parameter(Position=0, ValueFromPipeline=$true, ValueFromPipelineByPropertyName=$true, ParameterSetName="notVM", HelpMessage='Enter the computer name')]
[Parameter(Position=0, ValueFromPipelineByPropertyName=$true, ParameterSetName="byName", HelpMessage='Enter the computer name of the guest virtual machine')]
[Parameter(Position=0, ValueFromPipelineByPropertyName=$true, ParameterSetName="byID", HelpMessage='Enter the computer name of the guest virtual machine')]
[Parameter(Position=0, ValueFromPipelineByPropertyName=$true, ParameterSetName="byObj", HelpMessage='Enter the computer name of the guest virtual machine')]
[Alias('GuestName','GuestComputerName')] [String[]] $ComputerName=$env:COMPUTERNAME,
[Parameter(Position=1, Mandatory=$true, ValueFromPipelineByPropertyName=$true, ParameterSetName="byName", HelpMessage='Enter the computer name of the Hyper-V host')]
[Parameter(Position=1, Mandatory=$true, ValueFromPipelineByPropertyName=$true, ParameterSetName="byID", HelpMessage='Enter the computer name of the Hyper-V host')]
[Alias('host','server')] [String[]] $HostName,
[Parameter(Position=1, Mandatory=$true, ValueFromPipeline=$true, ValueFromPipelineByPropertyName=$true, ParameterSetName="byObj")]
[Alias('VirtualMachine')] [Microsoft.HyperV.PowerShell.VirtualMachine[]] $VM,
[Parameter(Position=2, Mandatory=$true, ValueFromPipelineByPropertyName=$true, ParameterSetName="byName", HelpMessage='Enter the name of the virtual machine in Hyper-V')]
[Alias('VirtualMachineName','Guest')][String[]] $Name,
[Parameter(Position=2, Mandatory=$true, ValueFromPipelineByPropertyName=$true, ParameterSetName="byID", HelpMessage='Enter the GUID of the virtual machine')]
[Alias('VirtualMachineId','vmid')][GUID[]] $ID
)
process {
Write-Host $PsCmdlet.ParameterSetName
}
}It seems to work as expected except for this example (sometimes the user will pipe in both Name and Id, and I cannot stop them):
New-Object –Typename PSObject –Prop @{'HostName'="hvsvr";'GuestComputerName'="mydc01";'VirtualMachineId'=[GUID]"837b8cbc-b89c-4070-bf65-4b674bb380e4";'VirtualMachineName'="TheDC"} | Get-MemoryUsage
#Error:
Get-MemoryUsage : Parameter set cannot be resolved using the specified named parameters.
At line:1 char:200
+ ... TheDC} | Get-MemoryUsage+ ~~~~~~~~~~~~~~~+ CategoryInfo : InvalidArgument: (@{VirtualMachin...m3 server 2012}:PSObject) [Get-MemoryUsage], ParameterBindingException+ FullyQualifiedErrorId : AmbiguousParameterSet,Get-MemoryUsage
#If I remove either the 'VirtualMachineName' or 'VirtualMachineId' property, it works. Or if I remove the [GUID] cast, it works.How can I fix this?
This whole declaration seems sloppy to me. Is there a better way? Suggestions are welcome.
-Tony