所有VM PowerCLI信息输出/控制台和自定义对象均无法正常运行

时间:2019-03-26 10:53:31

标签: powershell powercli

我想使用vSphere PowerCLI获取所有虚拟机,并输出一些其他信息。但是我没有使输出正常工作。

我已经尝试将其作为控制台输出,但是后来却没有获得带有操作系统和IP地址的名称

$Object = New-Object PSObject -Property @{
    Name = $name
    OS = $info.OSFullName
    IP = $info.IPAddress
    }

Connect-VIServer -Server VMServer -Credential admin -Password ASecretPWnoOneKnows

$allnames = Get-VM

foreach($name in $allnames)
{
    $info = Get-VMGuest $name | select OSFullName, IPAddress
    Add-Member -InputObject $Object
}

到目前为止,这是我的“最佳方法”。

我的结果应类似于

SomeVMname SomeOS SomeIP

但是由于我没有正确处理自定义对象,我到目前为止只得到了总String或错误的Length

因此,如果有人可以通过控制台输出或我可以导出到csv的对象来帮助我,我将对此感到非常满意

2 个答案:

答案 0 :(得分:2)

您已经非常接近完成这项工作了。您只需要在$object循环中移动ForEach的创建和检索。

Connect-VIServer -Server VMServer -Credential admin -Password ASecretPWnoOneKnows
$allnames = Get-VM

$Output = foreach($name in $allnames)
{
  $Object = [PSCustomObject][ordered]@{
    Name=$name.Name
    OS=$name.Guest.OSFullName
    IP=$name.Guest.IPAddress -match "\." -join " "
  }
  $Object
}
$Output # To output to the console
$Output | Export-Csv -path "file.csv" -NoTypeInformaton # Csv output

AVShalom's helpful answer暗示了一些有关处理IPAddress属性和删除不必要的命令(即Get-VMGuest)以实现所需目标的想法。他使用快捷方式创建对象$row,该对象将保存虚拟机属性。但是,使用数组替换和附加技术$Report += Row会带来固有的效率低下,因为每次循环迭代时都会创建一个更大的新数组对象。对于较小的数据集,这可能并不重要,但是对于较大的数据集,这可能会很重要。

一旦创建[PSCustomObject],就可以在属性中编辑该值,只要该对象没有被破坏和/或那些属性定义保留在该对象上即可。这意味着您可以在循环的每次迭代期间为相同属性使用所有新值(如果需要)。我添加了[ordered]属性,以使$object属性顺序在您的输出中保持一致。

我添加了$Output变量以在循环的每次迭代期间存储$Object的值。 $Output成为具有您要跟踪的三个属性的对象的数组。现在,您的Export-Csv会将这些属性值转换为CSV文件的字符串。

我删除了Get-VMGuest命令,因为$name变量是一个对象,其中包含您已经需要的所有信息。 Guest属性提供Get-VMGuest提供的信息。

您可以将IPAddress的值强制转换为字符串,因为由于该属性是一个数组,因此有时可能会有多个IP。您可以选择仅获取索引值($Name.Guest.IPAddress[0]);但是,您必须注意这一点,因为所需的IP地址可能在另一个索引中。 [string]强制转换将使用空格定界符返回该属性的所有值。我改用-join运算符,并使用空格定界符。 IPAddress也可能包含IPv6地址。我只想捕获IPv4地址,所以我使用了Regex匹配,例如$Name.Guest.IPAddress -match "\.",与文字.字符匹配。您可以结合多种技术来获取所需的数据。

请考虑以下对象和示例:

$name.guest

IPAddress                                     OSFullName
---------                                     ----------
{1.1.1.1, 2.2.2.2, fe80::ffff:ffff:ffff:ffff} Windows StackOverflow

$name.guest.IPAddress # Retrieves all IPs
1.1.1.1
2.2.2.2
fe80::ffff:ffff:ffff:ffff

$name.guest.IPAddress[0] # Retrieves the first IP in the array
1.1.1.1

$name.guest.IPAddress -match "\." # Retrieves all IPv4 IPs
1.1.1.1
2.2.2.2

$name.guest.IPAddress -match "\." -join " " # Retrieves all IPv4 separated by space
1.1.1.1 2.2.2.2

使用代码的结构方式,似乎就像您试图创建其值是通过引用而不是通过值的属性一样。为了进一步说明,您似乎希望$Object的属性值随着$info属性值的更改而自动自动更改而没有明确的分配。我不知道这是否是您的意图,但我相信这会增加您要完成的工作的复杂性。我没有为您的代码执行此操作。每次循环迭代时,我都会显式设置$Object属性值。

我也没有看到您的Export-Csv命令;但是,您描述了Length属性的输出。当您使用Export-Csv对象作为输入对象[string]时,可能会发生这种情况。由于Export-Csv的目的是将属性值转换为字符串,因此常规字符串的唯一属性值为Length。因此,这是可以预期的。您可以在下面看到此行为:

$str = "this is a string"
($str | Get-Member).where({$_.MemberType -eq "Property"})


   TypeName: System.String

Name   MemberType Definition
----   ---------- ----------
Length Property   int Length {get;}
$str | ConvertTo-Csv
#TYPE System.String
"Length"
"16"

答案 1 :(得分:0)

您不需要使用Get-VMGuest来获取OS / IP信息,您已经使用Get-VM属性成员将其与Guest一起使用了:

应该那样简单:

Connect-VIServer -Server VMServer -Credential admin -Password ASecretPWnoOneKnows

$Report = @()
$VMs = Get-VM
foreach ($vm in $VMs)
{
$row = "" | Select Name,OSFullName,IP
$row.Name = $vm.name
$row.OSFullName = $vm.Guest.OSFullName
$row.IP = $vm.Guest.IPAddress[0]
$Report += $row
}
  • 请注意,IP地址可能包含一个以上的IP,例如IPV4 / V6,在示例中,我收集了第一个[0],您可以使用正则表达式来匹配特定的模式