If your PowerCLI script is slow and you are piping the output of Get-VM, Get-VMHost, Get-Datastore, or some other such Get-(vSphereManagedObject) cmdlet into Get-View, then you may be able to improve its performance dramatically with a few simple modifications. See an example of the below changes in practice.

  1. Instead of piping the output of Get-VM into Get-View like this:

    Get-VM | Get-View

    use Get-View without first calling Get-VM and specify the managed object type as a parameter, like this:

    Get-View -ViewType VirtualMachine

    Similarly, if you’re using Get-VMHost, change this:

    Get-VMHost | Get-View

    to this:

    Get-View -ViewType HostSystem

    In each case, piping get-vm or get-vmhost into get-view is dramatically slower than using get-view and specifying the ViewType. If you have 1000 VMs, get-vm | get-view calls get-view 1000 times. Get-VM or Get-VMHost retrieves a list of VirtualMachine or HostSystem managed objects and piping that list to Get-View causes get-view to be called on each item in the list, so that a view is generated for each item one at a time. The second version of the command calls get-view just once and generates view objects for all the VMs or Hosts within that one call, and this works much faster.

    Possible values for ViewType are: ComputeResource, ClusterComputeResource, Datacenter, Datastore, Network, DistributedVirtualPortgroup, DistributedVirtualSwitch, Folder, HostSystem, ResourcePool, VirtualApp, VirtualMachine, and VmwareDistributedVirtualSwitch.

  2. Instead of making get-view retrieve every available property of a managed object like this:
    Get-View

    we can limit the properties that get-view retrieves to just the ones needed in our script (in this case, Name and Config.Product.*):

    Get-View -ViewType HostSystem -Property Name,Config.Product

    This improves performance noticeably if you only need a few properties and you know up front what they are.

  3. You might not need to use get-view at all if a cmdlet like get-vm, get-vmhost, or get-datastore can provide you with the properties that you need. When you run get-vm you see something like this

    Name                 PowerState Num CPUs Memory (MB)
    ----                 ---------- -------- -----------
    vm1                  PoweredOn  4        2048
    vm2                  PoweredOn  1        4096
    vm3                  PoweredOff 1        476
    ...
    

    But more properties are available from the managed objects returned by get-vm than the above console output leads you to believe. If you run

    Get-VM | Get-Member

    Then you can see the full list of properties and functions of a VirtualMachine managed object:

       TypeName: VMware.VimAutomation.Client20.VirtualMachineImpl
    
    Name                MemberType Definition
    ----                ---------- ----------
    Equals              Method     bool Equals(System.Object obj)
    GetHashCode         Method     int GetHashCode()
    GetType             Method     type GetType()
    ToString            Method     string ToString()
    CDDrives            Property   VMware.VimAutomation.Types.CDDrive[] CDDrives {get;}
    CustomFields        Property   System.Collections.Generic.IDictionary`2[[System.String, msc...
    Description         Property   System.String Description {get;}
    DrsAutomationLevel  Property   System.Nullable`1[[VMware.VimAutomation.Types.DrsAutomationL...
    FloppyDrives        Property   VMware.VimAutomation.Types.FloppyDrive[] FloppyDrives {get;}
    FolderId            Property   System.String FolderId {get;}
    Guest               Property   VMware.VimAutomation.Types.VMGuest Guest {get;}
    HAIsolationResponse Property   System.Nullable`1[[VMware.VimAutomation.Types.HAIsolationRes...
    HardDisks           Property   VMware.VimAutomation.Types.HardDisk[] HardDisks {get;}
    HARestartPriority   Property   System.Nullable`1[[VMware.VimAutomation.Types.HARestartPrior...
    Host                Property   VMware.VimAutomation.Types.VMHost Host {get;}
    HostId              Property   System.String HostId {get;}
    Id                  Property   System.String Id {get;}
    MemoryMB            Property   System.Int32 MemoryMB {get;}
    Name                Property   System.String Name {get;}
    NetworkAdapters     Property   VMware.VimAutomation.Types.NetworkAdapter[] NetworkAdapters...
    Notes               Property   System.String Notes {get;}
    NumCpu              Property   System.Int32 NumCpu {get;}
    PowerState          Property   VMware.VimAutomation.Types.PowerState PowerState {get;}
    ResourcePoolId      Property   System.String ResourcePoolId {get;}
    

    So, for example, guest OS properties such as the IP addresses or the list of HardDisks are available just from using get-vm, without calling get-view, and these run quickly even for a large inventory of VMs:

    Get-VM | select name, { $_.Guest.IPAddress }
    Get-VM | foreach {$_.HardDisks}