So I was working on a script and found an unusual behavior:
$Drives = Get-WmiObject -Class Win32_logicalDisk -Filter 'DriveType=3' | Select -ExpandProperty DeviceID #this will exclude CD drives and shared drives, etc, returning only local logical drives.
$MisconfiguredConfigFiles = [List[object]]::new()
$AllConfigFiles = [List[object]]::new()
foreach ($drive in $Drives) {
$ConfigFiles = dir "$drive\*.config" -Recurse
$AllConfigFiles.Add($ConfigFiles.FullName)
}
If I do $AllConfigFiles.Count
with that code, it gives me the number of drives instead of the number of files. But if I do this:
$Drives = Get-WmiObject -Class Win32_logicalDisk -Filter 'DriveType=3' | Select -ExpandProperty DeviceID #this will exclude CD drives and shared drives, etc, returning only local logical drives.
$MisconfiguredConfigFiles = [List[object]]::new()
$AllConfigFiles = @()
foreach ($drive in $Drives) {
$ConfigFiles = dir "$drive\*.config" -Recurse
$AllConfigFiles += $ConfigFiles.FullName
}
Then, $AllConfigFiles.Count
will return the accurate number of files I was expecting. How can I continue to use the List object (and its correlated "Add" method) instead of an array using the "+=" operator?
The "direct" answer is Mathias': you are adding a collection, so you should use .AddRange()
.
+=
unpacks the collection automatically but that obviously is a problem if you want to add a collection as a single item :)
That said, the best way to deal with your needs is direct assignment.
# DO NOT USE WMI CMDLETS. It has been Obsoleted snce Powershell 3.
# And completely removed from 6+ .
# Use CIM ones instead.
# Force-casting removes a few hassle in calling the drive later on.
# Specifying the property on Get-CimInstance is mostly superfluous optimization
# in this case: it makes it so the cmdlet only returns that property of the
# device.
# I added it mostly as a Teaching Moment(TM) about Left Side Filtering.
[System.IO.DriveInfo[]]$DriveList = Get-CimInstance -Class Win32_logicalDisk -Filter 'DriveType=3' -Property DeviceID |
Select-Object -ExpandProperty DeviceID
# Force-casted direct assignment FTW.
# If you do NOT need to add\remove items AFTER the collection has been created,
# remove the casting and you'll have a nice Array perfectly fine to use.
[System.Collections.Generic.List[object]]$AllConfigFiles = foreach ($Drive in $DriveList) {
# Evaluate adding -Force, -Depth and -ErrorAction SilentlyContinue .
Get-ChildItem -LiteralPath $Drive -File -Filter '*.config' -Recurse
}
$AllConfigFiles.Count