PowerCLI

 View Only
  • 1.  Add VMs to Inventory PoSh

    Posted Dec 09, 2025 02:59 PM
    Edited by Roger Haines Dec 09, 2025 03:20 PM

    I want to modify the script below to include all the servers from a CSV file in the format below, then everything included in the "SearchResult" line in the script.  ie..  "$SearchResult = $dsBrowser.SearchDatastoreSubFolders($DatastorePath, $SearchSpec) | where {$_.FolderPath -notmatch ".snapshot"} | %{$_.FolderPath + ($_.File | select Path).Path}"

    Name
    server1
    server2
    server3
    server4
    server5

    $Cluster = "TEST"
    $Datastores = "snap*"
    $VMFolder = "ReplicationRecovery"
    $ESXHost = Get-Cluster $Cluster | Get-VMHost | select -First 1
    $RGMachines = Get-Content C:\MasterRG.csv
     
    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
       }
    }

    I suspect I need to add something like below, but need some help.  @LucD

    Where-Object { $_.Name -in $vmList }



    -------------------------------------------



  • 2.  RE: Add VMs to Inventory PoSh

    Posted Dec 10, 2025 03:11 PM

    Anyone?  I'm stumped! 

    Any help would be greatly appreciated!

    -------------------------------------------



  • 3.  RE: Add VMs to Inventory PoSh

    Posted Dec 11, 2025 03:18 AM

    Well, I took a different approach when searching for files on a datastore.
    Basically I mount each datastore (New-PSDrive) and use standard Powershell commands (Get-ChildItem) to find the files I'm searching for.

    Something like:

    $vcname   = YourVCName
    $dsname   = YourDatastoreName

    $vc       = connect-viserver $vcname
    $dsobject     = Get-Datastore -Name $dsname -Server $vc
    $psdrive      = New-PSDrive -datastore $dsobject -Name $dsobject.Name -PSProvider VimDatastore -Root \ 

    $vmxlist = Get-ChildItem ${psdrive}:\ -Include *.vmx -Recurse
    $vmxlist |select Name, FolderPath

    You may want to 'enhance' the -Include statement in order to limit the search path.
    Or you could just omit the -Include part, collect a list of all files and then select the vmx files.

    -------------------------------------------



  • 4.  RE: Add VMs to Inventory PoSh

    Posted Dec 11, 2025 04:15 PM

    Thanks for your reply Alex.  I took a stab at letting AI fix it.  See below, now I think the issue is related to using the "Import-CSV" cmdlet.  When I use Export-CSV to export the output, it shows as numbers.

    # Requires the VMware PowerCLI module
    Import-Module VMware.PowerCLI
     
    # NOTE: Ensure you are connected to vCenter via Connect-VIServer -Server <vCenterName>
     
    # --- Configuration Variables ---
    $ClusterName = "TEST"
    # Use a wildcard for the datastore pattern
    $DatastorePattern = "snap*" 
    $VMFolderName = "Recovery"
    # Path to the CSV file containing the names of the VMs you want to find
    $InputCSVPath = "C:\Input\Master.csv"
     
    # --- Pre-requisite Setup ---
     
    # Get the target ESX host (the first host found in the cluster)
    $ESXHost = Get-Cluster $ClusterName | Get-VMHost | Select-Object -First 1
    if (-not $ESXHost) {
        Write-Error "Could not find a valid ESX host in cluster $ClusterName."
        exit
    }
     
    # Ensure the target VM folder exists, create it if not
    $TargetVMFolder = Get-Folder -Name $VMFolderName -ErrorAction SilentlyContinue
    if (-not $TargetVMFolder) {
        Write-Host "Creating VM folder: $VMFolderName"
        $TargetVMFolder = New-Folder -Name $VMFolderName
    }
     
    # Load the desired VM names from the input CSV into an array
    # Assuming the CSV has a column header named 'Name' (adjust 'Name' if needed)
    try {
        $TargetVMNames = Import-Csv -Path $InputCSVPath | Select-Object -ExpandProperty Name
    } catch {
        Write-Error "Failed to import CSV file from $InputCSVPath. Check file path and format."
        exit
    }
     
    # Array to store the paths of the found VMX files
    $FoundVMXFiles = @()
     
    # --- Search Logic ---
     
    Write-Host "Starting search for VM names listed in $InputCSVPath..."
     
    # Set up the search criteria once
    $SearchSpec = New-Object VMware.Vim.HostDatastoreBrowserSearchSpec
    $SearchSpec.matchpattern = "*.vmx"
     
    # Iterate through all datastores matching the pattern
    foreach ($Datastore in Get-Datastore -Name $DatastorePattern) {
        Write-Host "Searching datastore: $($Datastore.Name)..."
     
        # Get the view/internal object reference for the datastore browser
        $dsBrowser = Get-View $Datastore.Extensiondata.Browser
     
        # Define the base path for the search
        $DatastorePath = "[" + $Datastore.Name + "]"
     
        # Execute the search using the API method SearchDatastoreSubFolders
        # We use a Where-Object filter immediately to remove snapshot folders
        $searchResults = $dsBrowser.SearchDatastoreSubFolders($DatastorePath, $SearchSpec) | 
            Where-Object { $_.FolderPath -notmatch ".snapshot" }
     
        # Process the results
        foreach ($folder in $searchResults) {
            foreach ($file in $folder.File) {
                $vmxPath = $folder.FolderPath + $file.Path
     
                # Extract the VM name guess from the folder path containing the VMX file
                $vmNameGuess = ($vmxPath.Split('/')[-2]).Trim()
     
                # Check if this VM name is in our target list from the CSV
                if ($vmNameGuess -in $TargetVMNames) {
                    Write-Host "  [+] Match found: $vmNameGuess at $vmxPath"
                    $FoundVMXFiles += $vmxPath
                }
            }
        }
    }
     
    # --- Registration Logic ---
     
    if ($FoundVMXFiles.Count -eq 0) {
        Write-Warning "No matching VMX files were found."
    } else {
        Write-Host "Registering $($FoundVMXFiles.Count) found VMs..."
     
        foreach ($VMXFile in $FoundVMXFiles) {
            # Use New-VM to register the VM from its VMX file path
            # It's helpful to explicitly name the VM using our guess to match the input CSV name expectation
            $registerName = ($VMXFile.Split('/')[-2]).Trim()
            
            Write-Host "Registering $registerName from $VMXFile..."
            New-VM -Name $registerName -VMFilePath $VMXFile -VMHost $ESXHost -Location $TargetVMFolder -RunAsync
        }
        Write-Host "VM registration process initiated."
    }

    -------------------------------------------