Вы уже очень близки к выполнению этой работы.Вам просто нужно переместить $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
Полезный ответ А.В.Шалома ссылается на некоторые идеи, касающиеся обработки 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, поэтому я использовал совпадение с регулярным выражением, например, $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"