Jan 01 2020 08:55 AM - edited Jan 01 2020 08:59 AM
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!
Jan 19 2020 04:30 PM
Solution@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.
Jan 19 2020 04:30 PM
Solution@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.