Search code examples
powershellmemory-managementworkflow-foundation

Powershell Workflow Chugging at Memory and Crashing


I'm dabbling with workflows in powershell and I'm noticing some odd behavior. The below script will work when the directory doesn't contain a lot of files. After some point it will hold on line 6 (when run in the ise you'll see the workflow status bar), munch up memory, then eventually crash (after at least half an hour). This crash happens when the directory of files is at least 1.25GB, but not when the $Path has only 50mb of files. Here's an easy test:

Workflow Test-Me {
    Param
    (
        $Path = "c:\temp",
        $Days = 0
    )
    $Files = InlineScript{
                Get-ChildItem -Path $using:Path -File -Recurse -Force | Where-Object {$_.LastWriteTime -lt ((get-date).AddDays(-$using:Days))}
             }
    $Files
}

Now the odd thing is that when Get-ChildItem -Path $using:Path -File -Recurse -Force | Where-Object {$_.LastWriteTime -lt ((get-date).AddDays(-$using:Days))} is run from outside of the workflow (in a regular function or just on a line of the shell) it completes in less than a minute, even with 1.25GB of files.

What is the workflow doing that causes it to eat memory, take a long time, and crash? It's obviously doing something unexpected. Again, it works if there's only a few files in the directory.

Also, a solution/workaround would be great.

Research:

Activity to invoke the Microsoft.PowerShell.Management\Get-ChildItem command in a workflow

Running Windows PowerShell Commands in a Workflow


Solution

  • The problem here appears to be with the retention of object data. Adding a select reduces the size of the returned object data so much so that searching 100GB+ did not cause it to crash. Solution is as followed:

    Workflow Test-Me {
        Param
        (
            $Path = "c:\temp",
            $Days = 0
        )
        $Files = InlineScript{
                    Get-ChildItem -Path $using:Path -File -Recurse -Force | Where-Object {$_.LastWriteTime -lt ((get-date).AddDays(-$using:Days))} | select filename
                 }
        $Files
    }