How to Remote execute scripts inside a VM in vSphere

Published: Automation
Hello All,
Hope you are doing well. Today I want to talk about remotely executing scripts inside a VM which is hosted in vSphere environment. Recently I received the following requirement from a colleague for a customer.
Environment:
  • Customer has hundreds of VMs
  • A particular application is running in many of the VM's which creates a log file in a particular location inside the VM
  • Admin team does not know in which of those VM's the application is running
Requirement:
  • Admin team wants to know in which of those VM's the application is running.
  • They want to get the information in an excel file
Solution:

To provide a solution to this problem we would use the Invoke-Command cmdlet available in PowerShell. Note I used this cmdlet as all the VM's had Windows as an operating system. For more generic work (mixed environment) we can use Invoke-VMScript cmdlet available in PowerShell.

The difference between the two is given below:
Invoke-Command is a more specific cmdlet which works for Windows environment only. This cmdlet let's you run a command in the "local or remote" windows computers (be it physical or virtual).

On the contrary Invoke-VMScript is a very specific cmdlet provided with PowerCLI which is applicable for vSphere environment only. This cmdlet "Runs a script in the guest OS of each of the specified virtual machines" and this is valid of all guest operating system. This actually takes help of VMware tools to run the script remotely.
For my example, I took help of Invoke-Command and had written the following script.

#requires -version 3

###########################################################################################
# Title     :   Finding a list of VMs in which a particular file is present
# Filename  :   Get-File.ps1          
# Created by:   Sajal Debnath           
# Date      :   19-11-2015                
# Version   :   1.0        
# Update    :   This is the first version
# E-mail    :   sdebnath@vmware.com
###########################################################################################

<# 
    .Synopsis 
   Get-File finds whether a particular file is present in a location inside a Windows VM
    .DESCRIPTION 
   Get-File.ps1 is a script to find out a list of all the Windows VM's in a vSphere envionment inside which a particular file is present in a
   particular location.
   The output is provided in the console or optionally can be saved in csv format
   The script works on powered on VM's and only on those VM's where VMware Tools in installed.
   The script to be run with the following parameters
   Get-File -vcenter  -vcuser  -vcpassword  -guestuser  -guestpassword  -filelocation  -outputfile 

    .NOTES 
   Created by: Sajal Debnath 
   Modified: 19/11/2015 10:29:58 PM  

   Changelog: 
    *  
   To Do: 
    * 
    .EXAMPLE 
#> 

Param(
    [Parameter (Mandatory=$true, ValueFromPipeline=$false)]
    [String]$vcenter,
    [Parameter (Mandatory=$true, ValueFromPipeline=$false)]
    [String]$vcuser,
    [Parameter (Mandatory=$true, ValueFromPipeline=$false)]
    [String]$vcpassword,
    [Parameter (Mandatory=$true, ValueFromPipeline=$false)]
    [String]$guestuser
    [Parameter (Mandatory=$true, ValueFromPipeline=$false)]
    [String]$guestpassword
    [Parameter (Mandatory=$true, ValueFromPipeline=$false)]
    [String]$filelocation
    [Parameter (Mandatory=$false, ValueFromPipeline=$false)]
    [String]$outputfile
)

Begin{
    # Adding Snapin and Importing required Modules
    $snapinName = 'VMware.VimAutomation.Core'
    $snapinAdded = Get-PSSnapin | Select-String $snapinName
    if (!$snapinAdded)
    {
        Add-PSSnapin $snapinName
    }
    

    Try{
        Write-Verbose 'Connecting to vCenter Server'
        [void] (Connect-VIServer -Server $vcenter -User $vcuser -Password $vcpassword)
        $vcfullname = (Get-View ServiceInstance).Content.About.FullName
    }
    
    Catch{
        Write-Debug 'Could Not Connect to vCenter Server'
        Exit
    }
}

Process {

        # Collecting all the VM's that are poweredon and has VMware tools installed in it
        $vms = Get-VM | Where {($_.PowerState -eq 'PoweredOn') -and ($_.ExtensionData.Summary.Guest.ToolsStatus -eq 'toolsOk')}

        $information = @()
        foreach ($vm in $vms){
        $info = ""| Select Name,Status
        $body = Invoke-Command -ComputerName $vm -ScriptBlock {Dir $filelocation} -GuestUser $guestuser -GuestPassword $guestpassword -ErrorAction SilentlyContinue
        $info.Name = $vm.Name
        if ($body){
            $info.Status = 'File Exists'
        }
        Else{
            $info.Status = 'File Does Not Exist'
        }
        $information += $info 
        }
}

End {
    # Showing in the information in screen and if path provided then saving it in file
        Write-Host $information
        if ($outputfile){
            $information | Export-Csv -Path $outputfile -NoTypeInformation
        }
        Disconnect-VIServer -server $vcenter -Confirm:$false
}
   
The above script will check inside all the VM's for the presence of the file inside the VM and generate an excel file based on the finding.
You can run the script in the following format.
Get-File -vcenter  -vcuser  -vcpassword  -guestuser  -guestpassword  -filelocation  -outputfile