How to use the Invoke-VMScript PowerCLI cmdlet

Save to My DOJO

How to use the Invoke-VMScript PowerCLI cmdlet

 

 

 

In today’s post, I’ll be introducing a very useful PowerCLI cmdlet which should be a great asset to your troubleshooting and automation quests.

The Invoke-VMScript cmdlet is used to remotely execute commands and scripts in the guest OS running on a VM. The cmdlet can be used to target both Windows and Linux operating systems. This functionality comes in handy in those instances where network connectivity to a VM has been lost or when you need to automate tasks on one or more virtual machines.

 

Syntax


I’ll jump straight in and show you the basic syntax just to get you started. The minimal syntax required is as follows.

Invoke-VMScript -VM <VM> -ScriptText <commands> -GuestUser <administrator> -GuestPassword <password> -ScriptType <Bat, PowerShell, Bash>

The parameters to the cmdlet are mostly self-explanatory. Regardless, here’s an explanation for each:

  • VM – This represents the vm you wish target. We use something like $vm = get-vm -name <virtual machine name> to populate it.
  • ScriptText – This can represent a path to a script residing on the VM’s OS or simply a string of commands concatenated using the & operator.
  • GuestUser – An account with administrative privileges on the vm’s guest OS such as the administrator account.
  • GuestPassword – The password associated with the GuestUser administrative account.
  • ScriptType – Defines the type of script or commands being executed. The supported types are Bat (for Batch file), PowerShell or Bash script.

A complete list of parameters is available here.

 

Requirements


There are a number of prerequisites that must be met for the cmdlet to work properly. In no particular order, let’s go through them.

  1. PowerCLI has to be present on the machine off of which the cmdlet is run. I know this sounds obvious but you never know. The thing is that users new to VMware do tend to confuse PowerShell and PowerCLI.
  2. The vSphere user account with which the cmdlet is run must have read access to the folder containing the virtual machine and also be granted the VirtualMachine.Interaction.Console privilege. By vSphere account, I mean something like root if targeting a standalone ESX host or [email protected] in the case of vCenter Server.
  3. The target VM must be powered on with VMware Tools installed and running correctly.
  4. The machine from where the cmdlet is run must have unhindered access to TCP/UDP port 902 on the ESXi server hosting the VM being targeted.

In addition, different versions of vSphere must meet the following:

1) For vCenter Server and ESX(i) versions earlier than 5.0, you must:

  • Run the cmdlet using the 32-bit version of PowerCLI.
  • Ensure that TCP port 902 on the ESX server hosting the vm is accessible.

2) For vCenter Server and ESX(i) versions earlier than 4.1, you must also:

  • Ensure that the user account used to connect to the ESXi server has the VirtualMachine.Interact.Console privilege. If you’re using root, know that the privilege is granted by way of the account’s default settings. If some other account is used, you can check the assigned privileges as per Fig. 1.
Figure 1 - Granted privileges to a vSphere local user account

Figure 1 – Granted privileges to a vSphere local user account

 

3) For vCenter Server and ESX(i) 4.1 and later, make sure the account used to connect to the ESX host has VirtualMachine.Interact.GuestControl privileges.

4) For vCenter Server and ESX(i) 5.0 and later, the ESX account in addition must also be granted VirtualMachine.GuestOperations.Modify and VirtualMachine.GuestOperations.Execute privileges.

 

Usage examples


Example 1

Say you want to remotely display the contents of the root directory on C: for a VM called Windows 7. By remotely, I mean running the PowerCLI cmdlet inside a console on computer A whilst targeting computer B. The procedure I would use would be something like this:

Open a PowerCLI window and run this code:

Connect-VIServer <ESX IP address or FQDN>
$vm = Get-vm -name 'Windows 7'
Invoke-VMScript -vm $vm -ScriptText "dir c:\" -GuestUser 'jason' -GuestPassword '1qaz!QAZ' -ScriptType bat

Here’s the code explained:

  • Line 1 – Establish a connection to the ESX host or vCenter Server.
  • Line 2 – Use the $vm variable to hold a VM object representing the VM called ‘Windows 7’
  • Line 3 – Call Invoke-VMScript to execute the command “dir c:\” on the target VM. The output is returned to the PowerCLI window from which the cmdlet is run.
Figure 2 - Remotely listing the contents of the root folder on a Windows guest OS

Figure 2 – Remotely listing the contents of the root folder on a Windows guest OS

 

Example 2

You can also target Linux based operating systems. In the next example, I’m displaying the contents of the tmp folder off a VM set up as a VCSA. Notice that the ScriptType parameter is now set to Bash to reflect the fact that we’re targeting a Linux guest OS.

$vm = get-vm -Name 'vcsa-1.vsphere.local (16.51)'
invoke-vmscript -VM $vm -ScriptText "ls /tmp" -GuestUser root -GuestPassword 1qaz!QAZ -scripttype Bash
Figure 3 - Remotely listing the contents of the tmp folder on a vm running Linux

Figure 3 – Remotely listing the contents of the tmp folder on a vm running Linux

 

Undoubtedly, these are very basic examples which serve little purpose other than to explore the cmdlet’s syntax and operation which is what I’ve tried to show here.

 

Example 3

A more useful example is probably this one where netsh is used to set the IP settings for a newly deployed Windows virtual machine. In this case, I’d use something like this:

$cmd='netsh interface ip set address name="Local Area Connection" static 192.168.16.147 255.255.240.0 192.168.16.1 1'
invoke-vmscript -VM $vm -ScriptText $cmd -GuestUser jason -GuestPassword 1qaz!QAZ -ScriptType bat
Figure 4 - Setting static IP settings on a recently deployed Windows vm.png

Figure 4 – Setting static IP settings on a recently deployed Windows VM

 

Example 4

At this point, I must stress that on VMs running flavors of Windows, you will be limited in what you can execute by way of the User Account Control (UAC) settings. One example that comes to mind is one where slmgr.vbs is used to modify licensing on Windows. This method is often used to extend the evaluation period of a Windows operating system amongst other things.

In this example, we’ll pass the string ‘cscript c:\windows\system32\slmgr.vbs /rearm’ as the ScriptText parameter. Slmgr must be run using elevated privileges irrespective of it being run within an administrative context. Think of a UAC pop-up – Fig. 5 – that alerts you to a change about to occur. This happens irrespective of being logged in as an administrator or not.

Figure 5 - UAC prompt to allow changes to take place

Figure 5 – UAC prompt to allow changes to take place

 

The problem with this is that there is no way, as far as I know, to interact with UAC when the Invoke-VMScript cmdlet is used, meaning that UAC has to be disabled if some invoked tasks are to complete successfully. Figure 6 shows how to disable UAC under Windows 7.

Figure 6 - UAC settings on Windows 7

Figure 6 – UAC settings on Windows 7

 

As per Fig.7, The slmgr /rearm command works great when UAC is disabled.

Figure 7 - Remotely re-arming the Windows license on a Windows 7 vm

Figure 7 – Remotely re-arming the Windows license on a Windows 7 vm

 

Another gotcha to be aware of, is the requirement to be interactively logged in the VM’s guest OS for this to work. Failing this, you will end up with an Access Denied error. I’m pretty sure there’s a workaround but to be honest I haven’t tried looking for one.

Returning to UAC, if it is set to anything other than that shown in Fig.6, the error seen in Figure 8 will be returned. As mentioned, the only workaround I know of is to completely disable UAC.  This compromise may be unacceptable to many out of security concerns and what have you, so you’ll need to get creative if this is the case. As always, experimentation and Google are your best friends!

Figure 8 - 'Access Denied' when performing an interactive task

Figure 8 – ‘Access Denied’ when executing a task that requires elevated privileges while UAC is enabled.

 

Conclusion


As we have seen, the Invoke-VMScript cmdlet has the potential to automate mundane tasks that would otherwise have to be carried out manually. The cmdlet is thus a valuable tool in anyone’s arsenal of tricks. The ability to remotely reboot a virtual machine when network connectivity to it is lost, for instance, is a great thing to have if you ask me!

[the_ad id=”4738″][the_ad id=”4796″]

Altaro VM Backup
Share this post

Not a DOJO Member yet?

Join thousands of other IT pros and receive a weekly roundup email with the latest content & updates!

Leave a comment

Your email address will not be published.