3

In this piece of code I'm getting a "UseDeclaredVarsMoreThanAssignments" warning from PSScriptAnalyzer

$lastUpdate = $false;
$shouldUpdate = $false;
if (Test-Path $logfile) {
    (Get-Content $logfile) | Where-Object {
        $_ -match "([^-]*)->\s*UpdateCheck"
    } | ForEach-Object {
        $lastUpdate = $Matches[1]
    }
    if ($lastUpdate) {
        $shouldUpdate = (Get-Date $Matches[1]) -lt ((Get-Date).AddDays(-7))
    } else {
        $shouldUpdate = $true;
    }
} 

The variable that triggers the warning is $lastUpdate in this line:

$lastUpdate = $Matches[1]

despite the fact that it's used int the next line.

Is this a problem with my code - I'm guessing it has something to do with scope and the ForEach-Object loop - or is the problem with PSScriptAnalyzer in VSCode?

Ansgar Wiechers
  • 193,178
  • 25
  • 254
  • 328
stib
  • 3,346
  • 2
  • 30
  • 38
  • i show the same incorrect "not used" msg for both `ShouldUpdate` and for `$LastUpdate`. to me, it looks like a bug. my setup >>> VSC = 1.36.1 & posh ext = 2019.5.0 & posh = 5.1 & os = win7x64 ///// it shows on a number of my other scripts, also. – Lee_Dailey Jul 15 '19 at 05:39
  • 2
    I have reported the same bug under issue [#1164](https://github.com/PowerShell/PSScriptAnalyzer/issues/1163), as far as I can tell PSScriotAnalyzer should exclude all the standard cmdlets that run in the current scope. – iRon Jul 15 '19 at 06:01

1 Answers1

1

As mentioned in the comment, the bug is issued at #1164

As a workaround you might consider using the ForEach statement rather than the ForEach-Object cmdlet (see: Difference between ForEach and ForEach-Object in powershell):

ForEach ($Item in ((Get-Content $logfile) | Where-Object {$_ -match "([^-]*)->\s*UpdateCheck"})) {
    $lastUpdate = $Matches[1]
}

In your case, you might even able to simplify your statement to just:

$lastUpdate = (Get-Content $logfile) | Where-Object {$_ -match "([^-]*)->\s*UpdateCheck"}

In this example $lastUpdate refers to a colection of matches which will cast to $True if it contains one or more items and to $False if it doesn't contain any matches.

iRon
  • 20,463
  • 10
  • 53
  • 79
  • Wow, I didn't even know that forEach ≠ ForEach-Object. Thanks. As far as the second snippet goes, I want $lastUpdate to equal the last instance of the match in the logfile, would that snippet work correctly if there were multiple matches? – stib Jul 17 '19 at 07:45
  • Yes, it should, I have added some explanation to the answer. – iRon Jul 17 '19 at 08:48
  • Thanks, that's better than a workaround, it's an improvement. So I could use `$lastUpdate = (Get-Content $logfile) | Where-Object {$_ -match "([^-]*)->\s*UpdateCheck"}; if ($lastUpdate){$lastupdate = $lastUpdate[-1]}` – stib Jul 17 '19 at 12:29