Forum Discussion
newb question: why is a foreach Item different from a Get-Item Item?!?
Here's my simple function test script and two use case tests:
# test rig for new function
function Test-FileNewerThanRefDate{
# return True if $vFile is new than $vRefDate, else return False
param(
$vFile,
[datetime] $vRefDate
)
if (($vFile.get_LastWriteTime() -gt $vRefDate) -or ($vFile.get_CreationTime() -gt $vRefDate)) {
return $true
} else {
return $false
}
}
$TestRefDate=[datetime]"9/30/2019"
# CASE #1
$Test1="\\DS218plus\home\other PSE catalogs\CMS 1976-7\CMS holiday 1976 00.jpg"
$Test2="\\DS218plus\home\other PSE catalogs\CMS 1976-7\IMG-3679.JPG"
$Test3="\\DS218plus\home\other PSE catalogs\CMS 1976-7\Thumbs.db"
foreach ($vTestCase in ($Test1, $Test2, $Test3)) {
if (Test-FileNewerThanRefDate (Get-Item $vTestCase -Force) $TestRefDate) {
Write-Host("newer")
}
}
# CASE #2
$TestPath="\\DS218plus\home\other PSE catalogs\CMS 1976-7\"
$vItems = Get-ChildItem -LiteralPath $TestPath -Force
foreach ($vItem in $vItems) {
if (-not ($vItem.PSIsContainer)) {
if (Test-FileNewerThanRefDate($vItem, $TestRefDate)) {
Write-Host("$vItem is newer")
}
}
}
The first use case works as desired; the function is correctly able to evaluate the creation and last write timestamps for the Get-Item() returned file.
The second use case fails. For some reason, the foreach ($vItem in $vItems) of the Get-ChildItems() list of items is getting passed to the function as a [System.DateTime] not a file-like object. The resulting error is:
Method invocation failed because [System.DateTime] does not contain a method named 'get_LastWriteTime'.
At C:\Users\lgg\Desktop\test.ps1:10 char:9
+ if (($vFile.get_LastWriteTime() -gt $vRefDate) -or ($vFile.get_Cr ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Why is the foreach item a different type of object than the Get-Item() object? What is the correct way to do this?
Thanks in advance for any suggestions or advice!
D_Watson2185 it looks like you're calling your function in two very different, but deceptively similar ways.
First, let's take a closer look at the params on your function:
param( $vFile, [datetime] $vRefDate )
So we're looking for two parameters, the first of which takes anything and the second should be a datetime (and if it isn't... PowerShell will try to cast it to one for you)In the sample that is working, you're passing the the variables to each of those parameters:
Test-FileNewerThanRefDate (Get-Item $vTestCase -Force) $TestRefDate
Or seen another way, that's:
Test-FileNewerThanRefDate $vFile $vRefDate
The second, failing sample is different:
Test-FileNewerThanRefDate($vItem, $TestRefDate)
What this actually doing is bundling up the two parameters as one, so both $vItem & $TestRefDate are being past to the function's vFile parameter as one "Object"
The "quick fix" is to change it to not use those parentheses and especially the comma:
Test-FileNewerThanRefDate $vItem $TestRefDate
This still doesn't sit well with me, as it relies on positioning and makes the function less maintainable later (e.g. adding a new parameter would break existing scripts that rely on it.) The better option is to specify the parameters by name:
Test-FileNewerThanRefDate -vRefDate $TestRefDate -vFile $vItem
Note, this allowed me to put the date first, and it still works.
D_Watson2185 it looks like you're calling your function in two very different, but deceptively similar ways.
First, let's take a closer look at the params on your function:
param( $vFile, [datetime] $vRefDate )
So we're looking for two parameters, the first of which takes anything and the second should be a datetime (and if it isn't... PowerShell will try to cast it to one for you)In the sample that is working, you're passing the the variables to each of those parameters:
Test-FileNewerThanRefDate (Get-Item $vTestCase -Force) $TestRefDate
Or seen another way, that's:
Test-FileNewerThanRefDate $vFile $vRefDate
The second, failing sample is different:
Test-FileNewerThanRefDate($vItem, $TestRefDate)
What this actually doing is bundling up the two parameters as one, so both $vItem & $TestRefDate are being past to the function's vFile parameter as one "Object"
The "quick fix" is to change it to not use those parentheses and especially the comma:
Test-FileNewerThanRefDate $vItem $TestRefDate
This still doesn't sit well with me, as it relies on positioning and makes the function less maintainable later (e.g. adding a new parameter would break existing scripts that rely on it.) The better option is to specify the parameters by name:
Test-FileNewerThanRefDate -vRefDate $TestRefDate -vFile $vItem
Note, this allowed me to put the date first, and it still works.