0

I'm working on an automated cleanup script that uses Get-ChildItem pretty liberally. I filter the contents to clean from an XML configuration with the -Include flag since it takes a string array while -Filter does not. Here's the offending block in question:

Function CleanFolders
{
  Write-Log 'Cleaning Folders..' status

  ForEach ($Folder in $Config.OS.$Build.Folders.Folder)
  {
    If (Test-Path $Folder.Name)
    {
      Try {
        GCI $Folder.Name -Include $Folder.Include -Recurse -Force |
          Where { ($_.Length -gt ([Int]$Folder.Threshold * 1MB)) -and
                  ($_.LastWriteTime -lt (Get-Date).AddDays(-[Int]$Folder.Expiration)) } |
          Sort $_.IsPSContainer -Descending |
          % {
            Try {
              Write-Log "Deleting $($_.FullName)"
              Remove-Item "$($_.FullName)" -Force
            } Catch {
              Write-Log 'Unable to delete item' error
              Write-Log "[$($_.Exception.GetType().FullName)] - $($_.Exception.Message)" error
            }
          }
      } Catch { Write-Log "[$($_.Exception.GetType().FullName)] - $($_.Exception.Message)" error }
    } Else { Write-Log "$($Folder.Name) does not exist" error }
  }
}

The script is run from a scheduled task as SYSTEM and for some reason, is not returning results from the -Include flag that are not just a wildcard *. Are there known issues with -Include? This operation runs properly when run as a user account with admin privileges.

Maximilian Burszley
  • 15,132
  • 3
  • 27
  • 49
  • @briantist That doesn't address my problem. It works when run as my admin account, but not as a scheduled SYSTEM account. – Maximilian Burszley Jul 31 '17 at 20:15
  • Why, then, would you think the problem is with `-Include` if the only difference is the credentials you're running under? Normally, `SYSTEM` should have access to all files, but it is of course possible to remove access from it, or specifically deny it access. Verify that the script works when running as `SYSTEM` with [`psexec -s`](https://docs.microsoft.com/sysinternals/downloads/psexec). If that works, something is going wrong with launching the script. – Jeroen Mostert Jul 31 '17 at 20:22
  • 1
    Should `GCI $Folder.Name` be `GCI $Folder.FullName`? Name is typically just the filename, and you'd want the full path. If default path for your account and SYSTEM is different (likely) then you'd see different behavior. Generally, however, I would avoid the `-Include` parameter entirely. It's flaky. I'd favor the `-Filter` parameter for wildcards, and `Where-Object` for anything more complex. I also wonder if you've got a scope problem because neither `$Config` nor `$Build` appear to be defined nor global/script scoped variables in your code. – Bacon Bits Jul 31 '17 at 20:27
  • @BaconBits I had a coworker assist me with it. It turns out the XML being loaded wasn't making the string an array, but a single string with commas which `-Include` was trying to take literally. Also `$Folder.Name` was referring to the XML object, not the actual folder. – Maximilian Burszley Jul 31 '17 at 22:36
  • @TheIncorrigible1 But that doesn't explain why the same code worked when you ran it? In any event, you should add your answer and mark the question answered. – Bacon Bits Aug 01 '17 at 17:57

1 Answers1

0

I found the problem with my script was my method of getting the xml into a variable. I was using Get-Content which did not preserve any formatting or type information, rather than Import-CliXml. This was causing the Get-ChildItem -Include arguments to be entered as a single string rather than a string array (since they were comma-separated in the xml).

My resolution around this was creating an object with defined types (such as the expected string array (String[]) rather than worrying about creating/exporting/importing an xml file.

$global:Config = @{
  OS = @{
    Workstation = @{
      Folders = @( @{ Name=..;Include=..;Expiration=..;Threshold=..;} );
    };
  };
};
Maximilian Burszley
  • 15,132
  • 3
  • 27
  • 49