none
Optimize PowerShell Script (VMWare) RRS feed

  • Question

  • Hello,

    I have created this PowerShell Script to an Inventory of Virtual Machine from vCenters, Script works just fine However it take very long time to provide the output I have around 5 vCenters and takes about couple of hours sometime more to give the output.

    Can anyone help me to Optimize this Script so that i can get output faster

    Import-Module VMware.VimAutomation.Core
    
    #Location of the OutPut File
        $outputfile = "D:\AllvCenterVMs_$(get-date -f MM-dd-yyyy).csv"
    
    #List all vCenters here
        $AllVCenters = ("vCenter1, vCenter2, vCenter3, vCenter4" )
    
    #Provide User Name
       $vuser = "<AccountName>"
    #Provide Pwd
       $vpass = "<Password Here>"
    #Connect to All vCenters
        Connect-VIServer $AllVCenters -user $vuser -password $vpass
    
        $output = @()
    $vms = Get-Vm
    
    foreach($vm in $vms){
    $vminfo = "" | Select vCenter, DataCenter, Cluster, Host, VMName, DNSName, IPAddres, OS, PowerState, vCPU, vRAM, ProvisionedDiskGB, UsedDiskGB, Datastore, ToolsStatus, ToolsVersion, AppName, Owner, AppAdmin, Environment, Notes
    $vmview = Get-VM $vm.Name | Get-View
    
    # Calculation for Provisioned Disk
        $ProvisionedDisk = [math]::round($vm.ProvisionedSpaceGB)
        $ProvisionedDisk =$ProvisionedDisk.ToString() 
    
    # Calucation for Used Disk
        $UsedDisk = [math]::round($vm.UsedSpaceGB)
        $UsedDisk =$UsedDisk.ToString() 
    
                $vminfo.vCenter = $vm.Uid.Substring($vm.Uid.IndexOf('@')+1).Split(":")[0]
                $vminfo.DataCenter = Get-Datacenter -VMHost $vm.VMHost
                $vminfo.Host = $vm.VMHost
                $vminfo.Cluster = get-cluster -VM $vm.Name
                $vminfo.VMName = $vm.Name
    	        $vminfo.DNSName = $vm.Guest.HostName
                $vminfo.IPAddres = $vm.Guest.IPAddress[0]
                $vminfo.OS = $vm.Guest.OSFullName
                $vminfo.PowerState = $vm.PowerState
                $vminfo.vCPU = $vm.NumCpu
    	    $vminfo.vRAM = $vm.MemoryGB.ToString()
                $vminfo.ProvisionedDiskGB = $ProvisionedDisk
    	    $vminfo.UsedDiskGB = $UsedDisk
                $vminfo.Datastore = Get-Datastore -Id $vm.DatastoreIdList
                $vminfo.ToolsStatus = $vmview.Guest.ToolsStatus
                $vminfo.ToolsVersion = $vm.Guest.ToolsVersion
                $vminfo.AppName = (Get-Annotation -Entity $vm -CustomAttribute AppName).Value
                $vminfo.Owner = (Get-Annotation -Entity $vm -CustomAttribute Owner).Value
                $vminfo.AppAdmin = (Get-Annotation -Entity $vm -CustomAttribute AppAdmin).Value
                $vminfo.Environment = (Get-Annotation -Entity $vm -CustomAttribute Environment).Value
                $vminfo.Notes = $vm.notes
    	        $output += $vminfo
    }
    
    # To Get OutPut in CSV format
            $output | Export-Csv $outputfile -noTypeInformation
    
    # To Get OutPut on PowerShell Grid
          # $output | out-gridview 
    
    #Disconnectin the vCenters sessions
            Disconnect-VIServer $AllVCenters -Force -Confirm:$false


    Nikhil Gupta

    Monday, November 25, 2019 10:40 PM

Answers

  • You are using a standard loop. Addressing Each Object before they continue, There is a few ways of doing this quicker. User Invoke-command -asjob . Not quite parallel processing, but more tan one job get run on the same time. Collect the information  once all jobs has completed.

    The other option is to user Powershell Workflows

    In the Foreach loop you can add the -Parallel switch.

     #Your Script with normal Loop

    Foreach ($i in (1..10))
    {
    Write-Output $i
    Start-sleep 1;
    }

    #Worflow Loop

    Workflow Get-Detail
    {

    Foreach -parallel ($i in 1..10)
    {
    Write-Output $i
    Start-Sleep 1

    }

    }
    Get-detail
    Thursday, December 5, 2019 9:02 PM

All replies