Home > PowerCLI, Powershell, vCenter, VMware > Adding .VMX Files to vCenter Inventory with PowerCLI gets even easier

Adding .VMX Files to vCenter Inventory with PowerCLI gets even easier

Update: I’ve since found out that mattboren actually found out about this before me and posted something on the VMware communities which I missed. Well found Matt.

A fairly common request is to be able to register existing VMs in a datastore in the vCenter inventory.

This can be a life saver if you have had storage issues and have had to present a backup copy of a datastore which has a different name and need to add the VMs to the inventory, a very laborious process if done manually with right-click Add to Inventory.

This can also be useful in a business recovery process when you need to add VMs that have been mirrored by storage replication over to a secondary site and you need to add them into your inventory.

PowerCLI guru, Luc Dekens has developed a fantastic script called Raiders of the Lost VMX which searches a datastore for .VMX files, and adds them to the vCenter inventory. This script has been updated over the years with even more clever functionality.

Adding the VM to the inventory involved running the RegisterVM_Task Method against the VM Folder in VC.

By accident I discovered there’s actually an updated easier way to add existing VMs to the inventory if you have the .VMX file path. I’m not sure when this was added to PowerCLI but I found it when writing a script to add a new VM.

The New-VM cmdlet now has a new parameter -VMFilePath which allows you to specify a path to the virtual machine you want to register.

This is in the format: [mydatastore] SERVER01/SERVER01.vmx

You can therefore use New-VM to add an existing VM to the VC inventory without having to invoke any MoRef!

In its simplest form:

$VMXFile = "[mydatastore] SERVER01/SERVER01.vmx"
$ESXHost = "VMHost01.local
New-VM -VMFilePath $VMXFile -VMHost $ESXHost

You can also use the rest of the New-VM parameters to specify a VM Folder Location and a Resource Pool.

$VMXFile = "[mydatastore] SERVER01/SERVER01.vmx"
$ESXHost = "VMHost01.local"
$VMFolder = Get-Folder "Prod Servers"
$ResPool = "Servers_Prod1"
New-VM -VMFilePath $VMXFile -VMHost $ESXHost -Location $VMFolder -ResourcePool $ResPool

Even in a single line:

New-VM -VMFilePath "[mydatastore] SERVER01/SERVER01.vmx" -VMHost "VMHost01.local" -Location (Get-Folder "Prod Servers" -ResourcePool "Servers_Prod1"

You can combine this with a simple yet powerful search to go through a set of datastores, find the .VMX files and add them to your Inventory

If you are using NFS and can see Snapshot folders when browsing the inventory you want to exclude these from the search results as they are storage snapshot copies of your VMs, a task easily done in PowerCLI.

$Cluster = "LON_PROD1"
$Datastores = "lonservers*"
$VMFolder = "LondonAppServers"
$ESXHost = Get-Cluster $Cluster | Get-VMHost | select -First 1

foreach($Datastore in Get-Datastore $Datastores) {
   # Set up Search for .VMX Files in Datastore
   $ds = Get-Datastore -Name $Datastore | %{Get-View $_.Id}
   $SearchSpec = New-Object VMware.Vim.HostDatastoreBrowserSearchSpec
   $SearchSpec.matchpattern = "*.vmx"
   $dsBrowser = Get-View $ds.browser
   $DatastorePath = "[" + $ds.Summary.Name + "]"

   # Find all .VMX file paths in Datastore, filtering out ones with .snapshot (Useful for NetApp NFS)
   $SearchResult = $dsBrowser.SearchDatastoreSubFolders($DatastorePath, $SearchSpec) | where {$_.FolderPath -notmatch ".snapshot"} | %{$_.FolderPath + ($_.File | select Path).Path}

   #Register all .vmx Files as VMs on the datastore
   foreach($VMXFile in $SearchResult) {
      New-VM -VMFilePath $VMXFile -VMHost $ESXHost -Location $VMFolder -RunAsync
  1. August 11th, 2011 at 18:23 | #1

    Nice find, great script.

  2. WoodITWork
    August 12th, 2011 at 10:42 | #2

    Thanks, Luc, that’s great coming from the master himself!

  3. May 17th, 2013 at 08:17 | #3

    Thanks for sharing this script, saved me some time creating it myself 🙂
    One minor comment, the VM’s are not placed in the folder because the variable name is from ($Folder instead of $VMFolder).

    New-VM -VMFilePath $VMXFile -VMHost $ESXHost -Location $Folder -RunAsync

    New-VM -VMFilePath $VMXFile -VMHost $ESXHost -Location $VMFolder -RunAsync

    • WoodITWork
      May 19th, 2013 at 22:55 | #4

      Thanks for spotting that, corrected.

  4. Travis
    May 21st, 2013 at 21:14 | #5

    Hi — First let me say thanks I’ve been testing this script for a good chunk of the day and it’s working great! I’ve added a few lines to do the registering on multiple hosts to split the load, since I’m anticipating registering hundreds of guests. As an extremely novice scripter I do have one question.

    When I comment out the actual registering of the VM’s and replace it with this (to get a list of the VMX files it would register):

    foreach($VMXFile in $SearchResult) {
    #New-VM -VMFilePath $VMXFile -VMHost $ESXHost -Location $VMFolder -RunAsync

    I get duplicate VMX’s listed. I believe this is because we have various files named *.vmxf (linked VM files) or *.vmx~ (no clue what these are). I’m wondering if there is a way to specify it so only files ending EXACTLY in “*.vmx” should be registered. (I’ve been messing around with some $_.File -not “*.vmxf” attempts to do some hardcoded exclusions but no luck! hah)

    PS – Also get a few blank lines that list just the $DataStorePath, which are from Datastores that contain only VMDKs on them (from machines with disks on multiple datastores). I believe this is less of a concern, but curious all the same.

  5. Tim Gray
    November 15th, 2013 at 22:06 | #6

    I cam getting an
    “Exception calling “SearchDatastoresSubFolders” with “2” argument(s) error when I try to run this script.
    Does this script work on a ESXi 5.0 host and vSphere 5.0?

  6. Gavin
    August 2nd, 2014 at 04:29 | #7

    You are my hero, that’s all I need to say!

    • Julian Wood
      August 22nd, 2014 at 23:13 | #8

      Thanks, glad it was useful.

  7. ranvir
    October 27th, 2015 at 17:03 | #9

    @Tim Gray
    Hi Tim…I am getting the same Error, I wonder did you manage to resolve this? Can you please let me know ,How?

  8. Manoj
    May 30th, 2016 at 14:00 | #10

    Hello There,

    I am very new to scripting and not able to find issue. Need your help to fix this.

    I am working on a script to migrate a set of VM’s from Virtual Center 5.0 to to 5.5. When I am running below script getting below error.

    New-VM : Cannot validate argument on parameter ‘VMFilePath’. The argument is null or empty. Provide an argument that is not null or empty, and then try the command again.
    At C:\Users\msharm44\Desktop\VM Migration Scripts\VM MIG about to be final.ps1:82 char:24
    + New-VM -VMFilePath $vm.Path -VMHost (Get-Cluster $DestCluster | G …
    + ~~~~~~~~
    + CategoryInfo : InvalidData: (:) [New-VM], ParameterBindingValidationException
    + FullyQualifiedErrorId : ParameterArgumentValidationError,VMware.VimAutomation.ViCore.Cmdlets.Commands.NewVM

    …………………………………………………Scripts starts below………………………………………………….

    $SourceVC = “Server1.domain.COM”
    $DestVC = “Server2.domain.COM”
    $DestCluster = “Server2_Pod01_Development_06”
    $DestFolder = “VMs Windows”

    #$UserFile = “User.fil”
    #$PassFile = “Pass.fil”

    $cred = Get-Credential

    # Functions ———————————————————————————

    function Log ($text) {
    $stamp = (Get-Date).ToString(“HH:mm:ss.fff”)
    Write-Host “$stamp | $text”

    # Business part of script ——————————————————————-

    Start-Transcript -Path VM-Move-VC.log -Append

    # Disconnect any existing VI Server sessions
    if ($DefaultVIServers.Count) {
    Log(“Disconnect existing vCentre server connections…”)
    Disconnect-VIServer -Server * -Force -Confirm:$false

    # Connect to source VC
    try {
    Log “Connecting to $SourceVC”
    $VCconn = Connect-VIServer -Server $SourceVC -Credential $cred -errorAction Stop
    } catch {
    Log(“Unable to connect to vCentre – ” + $_)

    # Get list of VMs to move
    $VMs = Get-Content “C:\tmp\source.csv”
    Log “VMXs to reregister…”
    $VMs2Move = @()
    foreach ($vm in $VMs) {
    $vm2move = “” | Select Name, Path
    $vm2move.Name = $vm.name
    $vm2move.Path = $vm.ExtensionData.Config.Files.VmPathName
    $VMs2Move += $vm2move
    Log ($vm2move.Name + ” ” + $vm2move.Path)
    #$VMs | Get-View | %{$_.Config.Files.VmPathName} | Sort

    # Unregister VMs
    foreach ($vm in $VMs) {
    Log (“Unregister ” + $vm.Name)
    Remove-VM -VM $vm -DeletePermanently:$false -Confirm:$false

    Disconnect-VIServer -Server $VCconn -Confirm:$false

    # Connect to destination VC
    try {
    Log “Connecting to $DestVC”
    $VCconn = Connect-VIServer -Server $DestVC -Credential $cred -errorAction Stop
    } catch {
    Log(“Unable to connect to vCentre – ” + $_)

    # Register VMs
    foreach ($vm in $VMs2Move) {
    Log (“Register ” + $vm.Name)
    New-VM -VMFilePath $vm.Path -VMHost (Get-Cluster $DestCluster | Get-VMHost | Get-Random) -Location (Get-Folder $DestFolder)

    Disconnect-VIServer -Server $VCconn -Confirm:$false

  9. September 12th, 2018 at 04:51 | #11

    Hello my loved one! I wish to say that this article is awesome, nice
    written and come with almost all important infos.
    I would like to peer extra posts like this . https://Takarat.com/user/profile/489892

  10. September 13th, 2018 at 06:54 | #12

    Just desire to say your article is as astounding. The clearness to your publish is just nice and i can assume you’re an expert on this subject.

    Well along with your permission allow me to snatch
    your RSS feed to stay up to date with drawing close post.
    Thank you 1,000,000 and please keep up the gratifying work. https://anenii-noi.md/?option=com_k2&view=itemlist&task=user&id=1743869

  11. September 13th, 2018 at 23:17 | #13

    I’m not positive where you’re getting your information, but good topic.
    I must spend some time finding out much more or working out more.
    Thank you for fantastic information I was on the lookout for this
    info for my mission. http://ecomuseo-valborlezza.it/component/k2/author/591683

  12. September 14th, 2018 at 15:36 | #14

    Hi Dear, are you actually visiting this website daily, if so afterward you will definitely get good know-how. https://Szjyhy.com/isaacmontesfast5/arquivos-dicas-de-saude/

  13. September 17th, 2018 at 04:04 | #15

    It’s appropriate time to make some plans for the future and it is time to be happy.
    I’ve read this post and if I could I wish to suggest you few interesting things
    or tips. Perhaps you could write next articles referring to this article.
    I want to read more things about it! https://www.Edentro.com/index.php?page=user&action=pub_profile&id=17616

  14. September 18th, 2018 at 01:47 | #16

    Thanks for sharing your info. I really appreciate your efforts
    and I am waiting for your further post thank you once again. http://www.studioconsani.net/component/k2/itemlist/user/3153620

  15. October 10th, 2018 at 21:17 | #17

    I’m gone to inform my little brother, that he should also pay
    a visit this blog on regular basis to take updated from most up-to-date
    news update. http://browsermmorpg.net/index.php?a=stats&u=anavaz24876444

  16. October 13th, 2018 at 01:10 | #18

    Hurrah, that’s what I was searching for, what a data! existing
    here at this website, thanks admin of this website. http://www.minikami.it/?option=com_k2&view=itemlist&task=user&id=2969414

  17. October 15th, 2018 at 06:27 | #19

    Great items from you, man. I’ve take into account your stuff prior to and you’re just too wonderful.
    I actually like what you have obtained right here, really like what you are stating and the
    best way through which you assert it. You’re making it enjoyable and you continue to take care of
    to stay it smart. I cant wait to learn far more from you.
    This is really a terrific site. http://Facebay.hu/user/profile/2329759

  1. September 14th, 2011 at 10:33 | #1

Time limit is exhausted. Please reload the CAPTCHA.