VMware Cloud Community
vmpwcliuser31
Contributor
Contributor
Jump to solution

"Find VM" script not working on specific VMs

Hello all,

I have a script that is pretty basic: it connects to multiple vCenters and then receives one piece of information (the server name) from the user, then searches for that [VM] server throughout the multiple vCenters.

If it finds the VM, it then displays which vCenter it's in, how to connect to that vCenter (ie: what the URL is for it), etc...It works great for 99% of the VMs; however, late yesterday afternoon a co-worker found a couple VMs that it would error out on.

I tested the findVM script myself and saw the same results and now am baffled why these specific VMs are giving the error I'm seeing...

 

The error I see is:

Cannot convert the "System.Object[]" value of type "System.Object[]" to type "System.Uri".

 

So far the VMs that I'm receiving the above error on is in, let's say, vCenter X.  There are plenty of other VMs in that same vCenter that the script works just fine.

 

I want to say one of the servers that my co-worker had issues with worked after he powered it down (it was being decommissioned anyways), but I can't say if I'm remembering that correctly or not.  Meaning while the server was powered on, the script gave that error above, but when the VM was powered off, the script worked just fine.

 

I'm not able to power off or restart the other servers I'm seeing the errors with since they're production servers, but did vMotion one of them to a different ESXi host just to see if that may 'kick it' and allow the script to work but to no avail.

 

Thoughts?

 

Snippet of my code is below:


Do {
$vm2find = Read-Host -Prompt 'Enter the server name'
Write-Host -ForegroundColor Yellow "Searching for the VM, please be patient...."
$vm = Get-VM -Name $vm2find

Try {
Get-VM -Name $vm2find -ErrorAction Stop | Out-Null
}
Catch {
Write-Host -ForegroundColor Red -BackgroundColor Black "----------------------------------------------------------------------"
Write-Host -ForegroundColor Red -BackgroundColor Black " "
Write-Host -ForegroundColor Red -BackgroundColor Black "Could not find $vm2find in any environment! Please verify the server name! "
Write-Host -ForegroundColor Red -BackgroundColor Black " "
Write-Host -ForegroundColor Red -BackgroundColor Black "----------------------------------------------------------------------"
$continue = Read-Host -Prompt 'Do you have another VM to find? Y or N'
}


switch(([uri]$vm.ExtensionData.Client.ServiceUrl).Host){
#----------------------------
#----------------------------
#vCenterX WORK STARTS HERE
#----------------------------
#----------------------------
'vCenterX' {
$vmnotes = Get-VM $vm | Select-Object -ExpandProperty Notes
Write-Host -ForegroundColor Green "$($vm.Name) is on $(([uri]$vm.ExtensionData.Client.ServiceUrl).Host)"
Write-Host -ForegroundColor Green 'The URL to get there is: https://vcenterx.local/ui'
Write-Host -ForegroundColor Yellow "Notes on the server are below: `n "
Write-Host -ForegroundColor Green "$vmnotes"
$continue = Read-Host -Prompt 'Do you have another VM to find? Y or N'
}

 

Reply
0 Kudos
1 Solution

Accepted Solutions
LucD
Leadership
Leadership
Jump to solution

The error means that you have more than 1 object in the $vm variable.
The cast to an Uri can only handle a String, not an array of strings.

You should investigate why

$vm = Get-VM -Name $vm2find

returns more than 1 object.
Could be VMs with the same name on different vCenters, or it could be that you have multiple connections open to the same vCenter (check what is in $global:defaultVIServers).

Instead of using the content of $vm asis, you could loop over the content if $vm.Count is greater than 1


Blog: lucd.info  Twitter: @LucD22  Co-author PowerCLI Reference

View solution in original post

8 Replies
LucD
Leadership
Leadership
Jump to solution

The error means that you have more than 1 object in the $vm variable.
The cast to an Uri can only handle a String, not an array of strings.

You should investigate why

$vm = Get-VM -Name $vm2find

returns more than 1 object.
Could be VMs with the same name on different vCenters, or it could be that you have multiple connections open to the same vCenter (check what is in $global:defaultVIServers).

Instead of using the content of $vm asis, you could loop over the content if $vm.Count is greater than 1


Blog: lucd.info  Twitter: @LucD22  Co-author PowerCLI Reference

vmpwcliuser31
Contributor
Contributor
Jump to solution

Ah ha!

Thanks for nudging me in the right direction, LucD.  It does appear that there are multiple VMs with the same name in different vCenters (sigh).  

I'll see what I can do and look into the loop for the $vm.Count!

Reply
0 Kudos
LucD
Leadership
Leadership
Jump to solution

An other option is to use the Server parameter on the Get-VM cmdlet.
That way the cmdlet will only look in that specific vCenter.


Blog: lucd.info  Twitter: @LucD22  Co-author PowerCLI Reference

Reply
0 Kudos
vmpwcliuser31
Contributor
Contributor
Jump to solution

As far as the Server paramater, I think I'd prefer not to do that as I'd like to find the VM in all vCenters (even if there are duplicates).

I got a $vm.count going and working well (enough for me at the moment) and got a PSCustomObject to display the VMs and vCenters (when there's more than 1 VM w/the same name).

A couple of problems I'm having:

1. If I run the script as is, when I search for a VM that is in multiple vCenters, it will print out the PSCustomObject (nothing wrong with that as that is what I want); however, if I uncomment the "$continue" line (near the end of my code snippet below), it won't print that PSCustomObject table out until I hit either Y or N; why is that?

2. When I have the $continue line uncommented & run the script, it will work; however, if I search for a VM that's in multiple vCenters, and then hit 'y' to search for another VM, it gives the same "Cannot convert the "System.Object[]" error as before.  I'm assuming I don't have the "if $vmcount is greater than 1" section marked off to itself like I should...

 

Snippet code is below:

Do {
$vm2find = Read-Host -Prompt 'Enter the server name'
Write-Host -ForegroundColor Yellow "Searching for the VM, please be patient...."
$vm = Get-VM -Name $vm2find

Try {
Get-VM -Name $vm2find -ErrorAction Stop | Out-Null
}
Catch {
Write-Host -ForegroundColor Red -BackgroundColor Black "----------------------------------------------------------------------"
Write-Host -ForegroundColor Red -BackgroundColor Black " "
Write-Host -ForegroundColor Red -BackgroundColor Black "Could not find $vm2find in any environment! Please verify the server name! "
Write-Host -ForegroundColor Red -BackgroundColor Black " "
Write-Host -ForegroundColor Red -BackgroundColor Black "----------------------------------------------------------------------"
$continue = Read-Host -Prompt 'Do you have another VM to find? Y or N'
}

$vmcount = (Get-VM $vm | Measure-Object).Count

if($vmcount -gt 1){
Write-Host -ForegroundColor Yellow "There are "-NoNewline; Write-Host -ForegroundColor Red "$vmcount " -NoNewline; Write-Host -ForegroundColor Yellow "VMs with the name of $vm2find!"
Write-Host -ForegroundColor Yellow "Below is the list of all VMs with the $vm2find name and which vCenter they are in."
Get-VM $vm | % {
[PSCustomObject] @{
Name = $_.Name
vCenter = $_.Uid.Substring($_.Uid.IndexOf('@')+1).Split(":")[0]
}
}
#$continue = Read-Host -Prompt 'Do you have another VM to find? Y or N'
}

switch(([uri]$vm.ExtensionData.Client.ServiceUrl).Host){
#----------------------------
#----------------------------
#vcenterX WORK STARTS HERE
#----------------------------
#----------------------------
'vcenterX' {
$vmnotes = Get-VM $vm | Select-Object -ExpandProperty Notes
Write-Host -ForegroundColor Green "$($vm.Name) is on $(([uri]$vm.ExtensionData.Client.ServiceUrl).Host)"
Write-Host -ForegroundColor Green 'The URL to get there is: https://vcenterX.local/ui'
Write-Host -ForegroundColor Yellow "Notes on the server are below: `n "
Write-Host -ForegroundColor Green "$vmnotes"
$continue = Read-Host -Prompt 'Do you have another VM to find? Y or N'
}

While ($continue -eq 'Y')

Reply
0 Kudos
LucD
Leadership
Leadership
Jump to solution

Try something like this.
I made a few changes

Do {
  $vm2find = Read-Host -Prompt 'Enter the server name'
  Write-Host -ForegroundColor Yellow "Searching for the VM, please be patient...."

  Try {
    $vms = Get-VM -Name $vm2find -ErrorAction Stop

  if ($vms.Count -gt 1) {
    Write-Host -ForegroundColor Yellow "There are "-NoNewline; Write-Host -ForegroundColor Red "$vmcount " -NoNewline; Write-Host -ForegroundColor Yellow "VMs with the name of $vm2find!"
    Write-Host -ForegroundColor Yellow "Below is the list of all VMs with the $vm2find name and which vCenter they are in."
    $vms | ForEach-Object {
      [PSCustomObject] @{
        Name = $_.Name
        vCenter = $_.Uid.Substring($_.Uid.IndexOf('@') + 1).Split(":")[0]
      }
      } | Out-Default
  }
  else{
    switch (([uri]$vms.ExtensionData.Client.ServiceUrl).Host) {
      #----------------------------
      #----------------------------
      #vcenterX WORK STARTS HERE
      #----------------------------
      #----------------------------
      'vcenterX' {
        Write-Host -ForegroundColor Green "$($vms.Name) is on $(([uri]$vms.ExtensionData.Client.ServiceUrl).Host)"
        Write-Host -ForegroundColor Green 'The URL to get there is: https://vcenterX.local/ui'
        Write-Host -ForegroundColor Yellow "Notes on the server are below: `n "
        Write-Host -ForegroundColor Green $vms.Notes
      }
    }
  }
  } Catch {
    Write-Host -ForegroundColor Red -BackgroundColor Black "----------------------------------------------------------------------"
    Write-Host -ForegroundColor Red -BackgroundColor Black " "
    Write-Host -ForegroundColor Red -BackgroundColor Black "Could not find $vm2find in any environment! Please verify the server name! "
    Write-Host -ForegroundColor Red -BackgroundColor Black " "
    Write-Host -ForegroundColor Red -BackgroundColor Black "----------------------------------------------------------------------"
  }

  $continue = Read-Host -Prompt 'Do you have another VM to find? Y or N'

}   While ($continue -eq 'Y')

 


Blog: lucd.info  Twitter: @LucD22  Co-author PowerCLI Reference

vmpwcliuser31
Contributor
Contributor
Jump to solution

I plugged in the $vmcount variable and everything is working just fine now, thanks!  🙂

 

To see if I understand how you got the PSCustomObject to print properly every time,  reading up on the | Out-Default, that tells it to print the output to the host and then with the switch in the else{} statement, it works great, correct?

Reply
0 Kudos
LucD
Leadership
Leadership
Jump to solution

Yes, the PS output engine deduces the output on what was output before.
This can lead to incomplete output.
By using the Out-Default you ask in fact for a reset of what the PS output engine "remembers".

I did re-arrange some of the blocks in the script, like the Catch block.


Blog: lucd.info  Twitter: @LucD22  Co-author PowerCLI Reference

Reply
0 Kudos
vmpwcliuser31
Contributor
Contributor
Jump to solution

Okay thanks, I appreciate the information!  

Reply
0 Kudos