问题
I'm looking to do the Following Steps:
- Reading in a CSV File
- Add The Contents from the CSV File to An Array
- Compare the Contents from the CSV with the Contents from another Array
- If the Items in the Array aren't members of the CSV Array
- Send Email
I First Tried Running the Script with One Host Missing from the Reports2 CSV File, This Missing Host was displayed to the Console and Written to the Reports2 File, but Still when i Re-Run the Code it still displays the last Element (Host that was Missing From Reports2.CSV):
This is the script I'm currently working On:
EDIT: I have now edited the code snippet to reflect the working solution
$user = ''
$pswd = ''
$vCenter_Servers = ""
$now = Get-Date
$start = $now.AddDays(-15)
$esxiHosts = Import-CSV C:\Scripts\Report1.csv #Reading CSV File
$MaitanceMode = @()
$Ticket = @()
foreach($ESXI in $esxiHosts){
$Ticket += $ESXI | Select-Object -ExpandProperty Name
}
foreach($vCenter in $vCenter_Servers) {
$srv = Connect-VIServer -Server $vCenter -User $user -Password $pswd
Get-VMHost -PipelineVariable esx -Server $srv | Where-Object {$_.ConnectionState -eq 'Maintenance'} |
ForEach-Object -Process {
$maintEntered = Get-VIEvent -Entity $esx -Start $start -MaxSamples ([int]::MaxValue) -Server $srv |
Where-Object{$_ -is [VMware.Vim.EnteredMaintenanceModeEvent]}
if($maintEntered){
#Skipping
}
else {
$MaitanceMode += $esx | Select-Object -ExpandProperty Name
}
}
} #Ending ForEach Loop
$NoTicket = $MaitanceMode | Where {$Ticket -Contains $_}
$NoTicket
回答1:
You should instantiate your array containing the results as an empty array, probably before ForEach-Object -Process {...
with $MaitanceMode = @()
and when you want to add elements to it, replace this line:
$MaitanceMode = $esx | select name
by
$MaitanceMode += $esx | select name
Edit:
Further replace this line:
$esxiHosts = Import-CSV C:\Scripts\Report2.csv
by this line:
$esxiHosts = Import-CSV C:\Scripts\Report2.csv | Select-Object -ExpandProperty Name
and this line:
$MaitanceMode += $esx | select name
by this line:
$MaitanceMode += $esx | Select-Object -ExpandProperty Name
And don't forget to instantiate $MaitanceMode
as an empty array. This is now mandatory. Otherwise it will become a string and not an array.
回答2:
Despite the accepted answer from @Thomas, it is not correct to use the increase assignment operator (+=
) to create a collection in PowerShell. For one thing, it is a very expensive syntax.
see: Why should I avoid using the increase assignment operator (+=) to create a collection.
To build a collection of objects in PowerShell, you should use the PowerShell pipeline by removing the <variable> +=
of the concerned commands (this will leave the objects on the pipeline) and catch the whole collection by adding <variable> =
in front of the iterator (e.g. Foreach-Object
). By using this PowerShell syntax, there is no need to initiate the arrays ().<variable> = @()
Taking your script as an example:
$user = ''
$pswd = ''
$vCenter_Servers = ""
$now = Get-Date
$start = $now.AddDays(-15)
$esxiHosts = Import-CSV C:\Scripts\Report1.csv #Reading CSV File
$Ticket = foreach($ESXI in $esxiHosts){
$ESXI | Select-Object -ExpandProperty Name
}
foreach($vCenter in $vCenter_Servers) {
$srv = Connect-VIServer -Server $vCenter -User $user -Password $pswd
Get-VMHost -PipelineVariable esx -Server $srv | Where-Object {$_.ConnectionState -eq 'Maintenance'} |
$MaitanceMode = ForEach-Object -Process {
$maintEntered = Get-VIEvent -Entity $esx -Start $start -MaxSamples ([int]::MaxValue) -Server $srv |
Where-Object{$_ -is [VMware.Vim.EnteredMaintenanceModeEvent]}
if($maintEntered){
#Skipping
}
else {
$esx | Select-Object -ExpandProperty Name
}
}
} #Ending ForEach Loop
$NoTicket = $MaitanceMode | Where {$Ticket -Contains $_}
$NoTicket
来源:https://stackoverflow.com/questions/61227270/comparing-arrays-within-powershell