0

I have created below PowerShell script so far.

$myEsxis = Get-VMHost | Select Name,DatastoreIdList,ConnectionState -First 5
 $myEsxiHosts = @()
 foreach ($myEsxi in $myEsxis)
 { Try { $obj = New-Object psobject -Property @{
          "ESXiName" = ($myEsxi).Name
          "ClusterName" = (Get-Cluster -VMHost ($myEsxi).Name).Name
          "ConnectionState" = ($myEsxi).ConnectionState
          "PingState" = Test-Connection ($myEsxi).Name -ErrorAction 0 -Quiet -Count 1
          "PhyNIC" = ((Get-EsxCli -VMHost ($myEsxi).Name).network.nic.list() | Select @{ Name = 'NIC';  Expression = {"$($_.Name)/$($_.Speed)/$($_.LinkStatus)"}} ) -split(";")
          "NumVMs" = (Get-VM -Location ($myEsxi).Name).count
          "ConnectedDatastores" = foreach ($obj in ($myEsxi).DatastoreIdList) {Get-Datastore | Where {($_.Id -eq $obj) -and ($_.Name -notlike '*local*')} | Select-Object -ExpandProperty Name}
          "ESXiVersion" = (Get-VMHost -Name ($myEsxi).Name).ExtensionData.Config.Product.FullName
         }
       }

   Catch { $obj = New-Object psobject -Property @{
           "ESXiName" = ($myEsxi).Name
           "ClusterName" = $_.Exception.Message
           "ConnectionState" = $_.Exception.Message
           "PingState" = Test-Connection ($myEsxi).Name -ErrorAction 0 -Quiet -Count 1
           "NumVMs" = $_.Exception.Message
           "PhyNIC" = $_.Exception.Message
           "ConnectedDatastores" = $_.Exception.Message
           "ESXiVersion" = $_.Exception.Message
           }
         }
 $myEsxiHosts += $obj | Sort-Object -Property ESXiName | Select ESXiName,ClusterName,PingState,ConnectionState,NumVMs,@{Name='ConnectedDatastores';Expression={[string]::join(";", ($_.ConnectedDatastores))}},@{Name='PhysicalNIC';Expression={[string]::join(";", ($_.PhyNIC))}},ESXiVersion
 }
 $myEsxiHosts

I have below problems related to it:

  1. The column ConnectedDatastores gives continuous output data separated by a semicolon and I have tried Split() in various ways but didn't succeed.
  2. The column PhysicalNIC also gives same type of continuous output data with @{ and that also I couldn't eliminate.

I need ConnectedDatastores column to display each item in new line.
I need same with the PhysicalNIC output but without @{

  • 1
    Both columns are returning an `array` and not a `string` hence why you're seeing the result of both columns wrapped in `{ result1, result2 , ... }`. I assume what you want is convert those arrays into a multiline string, is that correct? – Santiago Squarzon Apr 15 '21 at 20:09
  • Thanks for the reply but I'm out of ideas. How do I achieve that? – Suman Chhetri Apr 16 '21 at 08:58

2 Answers2

2

Try this out, it should work:

$myEsxis = Get-VMHost | Select Name,DatastoreIdList,ConnectionState -First 5

# Using Generic List for efficiency
$myEsxiHosts = [system.collections.generic.list[pscustomobject]]::new()

# Wrapping the oneliners inside scriptblocks for readability
$phyNIC={
        ((Get-EsxCli -VMHost $myEsxi.Name).Network.NIC.List() |
        Select @{
            Name = 'NIC'
            Expression = {"$($_.Name)/$($_.Speed)/$($_.LinkStatus)"}
        }).NIC
}

$dataStores={
    foreach ($obj in $myEsxi.DatastoreIdList)
    {
        (Get-Datastore | Where {($_.Id -eq $obj) -and ($_.Name -notlike '*local*')}).Name
    }
}

foreach ($myEsxi in $myEsxis)
{
    Try
    {
        $myEsxiHosts.Add(
            [pscustomobject]@{
                ESXiName = $myEsxi.Name
                ClusterName = (Get-Cluster -VMHost $myEsxi.Name).Name
                ConnectionState = $myEsxi.ConnectionState
                PingState = Test-Connection $myEsxi.Name -ErrorAction 0 -Quiet -Count 1
                PhyNIC = & $phyNIC | Out-String # Executing the scriptblock with '&' and piping the result to Out-String to get our multiline string
                NumVMs = (Get-VM -Location $myEsxi.Name).count
                ConnectedDatastores = & $dataStores | Out-String
                ESXiVersion = (Get-VMHost -Name $myEsxi.Name).ExtensionData.Config.Product.FullName
        })
    }
    Catch
    {
        $myEsxiHosts.Add(
            [pscustomobject]@{
                ESXiName = $myEsxi.Name
                ClusterName = $_.Exception.Message
                ConnectionState = $_.Exception.Message
                PingState = Test-Connection $myEsxi.Name -ErrorAction 0 -Quiet -Count 1
                NumVMs = $_.Exception.Message
                PhyNIC = $_.Exception.Message
                ConnectedDatastores = $_.Exception.Message
                ESXiVersion = $_.Exception.Message
        })
    }
}

$myEsxiHosts | Sort-Object -Property ESXiName 

Edit: I might be wrong, but most of the times when I see this question, it is related to how the data is exported (CSV, Xlsx, etc). The problem of having an array property is that when we want to export the object, instead of displaying the contents of said property you will get the type as displayed below. There are several workarounds for this, i.e. -join if you want a single string with all the values and Out-String if you want your array to be displayed as multiline string.

There are a lot better explanation than I can give you around the internet, i.e.:

Array Property:

enter image description here

Array converted to multiline String:

enter image description here

Edit:

If the object is converted to HTML, instead of using Out-String you need to use -join '<br>' and then after the object is converted to HTML you need to replace '&lt;br&gt;' for '<br>'. This is very well explained here: Break lines in powershell array and then convert it to html?

As a test example you can try this:

(@(
[PSCustomObject]@{
    Name = 'Value'
    Arr = 1,2,3,4,5,6|Out-String
}

[PSCustomObject]@{
    Name = 'Value2'
    Arr = 1,2,3,4,5,6|Out-String
}

[PSCustomObject]@{
    Name = 'Value'
    Arr = 1,2,3,4,5,6 -join "<br>"
}

[PSCustomObject]@{
    Name = 'Value2'
    Arr = 1,2,3,4,5,6 -join "<br>"
})|ConvertTo-Html) -replace '&lt;br&gt;','<br>' > ./test.html

Which will look like this:

enter image description here

Santiago Squarzon
  • 41,465
  • 5
  • 14
  • 37
  • 1
    Might be worthwhile adding either some explanation to the answer, or some inline comments about what you're doing in the code – Mathias R. Jessen Apr 16 '21 at 13:46
  • @MathiasR.Jessen Agreed, added explanation as well as some inline comments. – Santiago Squarzon Apr 16 '21 at 14:29
  • That was a lot of new knowledge for me. I tried your script. However, my second part of the 1st requirement is still not fulfilled. The PhyNIC and ConnectedDatastores are showing continuous data, no line breaks. If I want to add column size for each column, where and how do I add? Or is there a better idea to add line break on each output object? – Suman Chhetri Apr 16 '21 at 17:57
  • @SumanChhetri I would need to see how they look like in order to give a proper answer, first run your `$myEsxis` line and then run both variables `$phyNIC` and `$dataStores` and execute them with `&`. If you can attach a screenshot of how they look like in your PS Host I'll try to help you. – Santiago Squarzon Apr 16 '21 at 18:08
  • Ok, you're converting the object to HTML, this is totally non related to the question and never specified. This is something you can achieve with [CSS](https://stackoverflow.com/questions/10937218/how-to-show-multiline-text-in-a-table-cell) or instead of using `Out-String` you can use `-join ''` and see if that works. – Santiago Squarzon Apr 17 '21 at 14:13
  • woah..... such quick response...!! super thanks. When I do `Format-List -Force` for output, it's giving correct line break. – Suman Chhetri Apr 17 '21 at 14:27
  • I just tried `ConnectedDatastores = (& $dataStores | Out-String) -join '
    '` and it made no difference.
    – Suman Chhetri Apr 17 '21 at 14:41
  • @SumanChhetri check the edits. This should explain how to break lines in an html table – Santiago Squarzon Apr 17 '21 at 14:58
  • 1
    Unfortunately, that edit didn't help me. However, finally I solved it by the CSS `white-space: break-spaces;` but anyways, you have provided me a different perspective. I will mark your script as answer. Thanks a ton. – Suman Chhetri Apr 17 '21 at 15:47
0

@santiago-squarzon helped me to remove @, { and ; from the report.
However, I was able to break the line using CSS white-space: break-spaces;.