Search code examples
powershellvisual-studio-codepowershell-isepowershell-core

Issue with code in VS Code vs Powershell ISE


I have been trying to figure out why a script is working in Powershell ISE and not in VS Code. The script compares contents of the User folder and compares those folders with a partial name match to csv files in a logs folder. The exports those results to a CSV file. The code doesn't work with the export pipe or without it. The ISE shows results expected but when put through VS Code the results are nowhere to be seen. Same code, same comments, same everything.

Code follows:

# C:\Logs and C:\Users arrays #

$Logs = Get-ChildItem \\computername\c$\Logs\*.csv
$User = Get-ChildItem \\computername\c$\Users

# Comparison of C:\Users with partial name match of files in C:\Logs #

 $Results =  Foreach ($Line in $User) {
                Foreach ($Line2 in $Logs) {
                   if ($Line2 -like "*${Line}*") {$Line2} 
    }
  }
 $Results | Select-Object Name, LastWriteTime | Sort-Object {$_.LastWritetime} -Descending #| Export-Csv -Path "C:\Install\ProfileDate.csv"

I've wracked my brain on this and I am convinced it's something simple that I'm just blanking on. Any help would be greatly appreciated.

Thanks!

Ran the same code through ISE and VS Code.


Solution

  • Preface:

    • The issue comes down to the differences between Windows PowerShell (the legacy, Windows-only, ships-with Windows edition) and PowerShell (Core) 7+ (the modern, cross-platform, install-on-demand edition), as detailed below.
      As such, the execution environments (ISE vs. Visual Studio Code) are incidental to the problem.

    • While these two PowerShell editions are largely compatible, there are unavoidable differences, and their number will grow over time, given that only PowerShell 7+ is still actively developed.


    Even though you've named your iteration variables $Line and $Line2, they do not contain lines, but System.IO.FileInfo and System.IO.DirectoryInfo instances, as emitted by Get-ChildItem.

    As such, you're relying on their implicit stringification in your -like operation, and the problem is that the stringification behavior of these types changed between Windows PowerShell (the only edition supported in the obsolescent[1] ISE) and PowerShell (Core) 7+ (which you happen to be running in Visual Studio Code):

    • In short: In Windows PowerShell, Get-ChildItem output situationally stringifies to the file/directory name only, whereas in PowerShell 7+ it always stringifies to the full paths.

    • The Get-ChildItem calls in your question happen to produce name-only stringification in Windows PowerShell; see this answer for background information.

    Therefore, to make your code work in PowerShell 7+ and exhibit the same behavior you saw in Windows PowerShell, you must explicitly refer to the .Name property of the objects output by Get-ChildItem:

    $Results = foreach ($dir in $User) {
      foreach ($file in $Logs) {
        if ($file.Name -like "*$($dir.Name)*") { $file } 
      }
    }
    

    [1] The Windows PowerShell ISE is no longer actively developed and there are reasons not to use it (bottom section), notably not being able to run PowerShell (Core) 7+. The actively developed, cross-platform editor that offers the best PowerShell development experience is Visual Studio Code with its PowerShell extension.