powershellerror-handlingicacls

How to capture all output from icacls.exe in PowerShell


We have a script that runs once a week and adjusts all permissions on a specific file share. I mainly use a PowerShell script for this but also execute icacls.exe in some parts. As there are lots of files, errors will occur when running icacls.exe

At the start of my script, I reset all permissions on each customer folder and after that on all its childitems. One part of this consists of resetting the object owner.

I'm calling icacls.exe like this.

$ICACLSResult = icacls "$OBJPath\*" /setowner $OBJOwner /t /c /q | Out-String

I then check the string $ICACLSResult for a specific text to check whether errors occured or not and also append the string itself to my error message.

if($ICACLSResult -notmatch "bei 0 Dateien ist ein Verarbeitungsfehler aufgetreten" -and $ICACLSResult -notmatch "Failed processing 0 files")
{
    Add-Error -SED ($ErrorMSG + $ICACLSResult) -Level 2 -AddErrorInfo $False -ExitScript $False

    Throw("AnErrorOccured")
}

However, the actual content of the variable $ICACLSResult looks like this.

Successfully processed 13970 files; Failed processing 5 files

But when I run the same command directly within the console, it looks like this.

PS C:\Users\User> $ICACLSResult = icacls "$OBJPath\*" /setowner $OBJOwner /t /c /q | Out-String

D:\Folder1\Folder2\Folder3\File.txt: The system cannot find the path specified.
D:\Folder1\Folder2\Folder3\File.txt: The system cannot find the path specified.
D:\Folder1\Folder2\Folder3\File.txt: The system cannot find the path specified.
D:\Folder1\Folder2\Folder3\File.txt: The system cannot find the path specified.
D:\Folder1\Folder2\Folder3\File.txt: The system cannot find the path specified.

PS C:\Users\User>

But again $ICACLSResult looks like this.

PS C:\Users\User> $ICACLSResult
Successfully processed 13970 files; Failed processing 5 files

PS C:\Users\User>

Without these detailed error messages, there's no use logging the variable $ICACLSResult since all it says is how many files failed but not which files specifically.

How can I get this additional info as well and store it in $ICACLSResult? All I want are the paths of the failed files.

What I've also tried so far

  1. $ICACLSResult = icacls "$OBJPath\*" /setowner $OBJOwner /t /c /q 2>&1
  2. $ICACLSResult = icacls "$OBJPath\*" /setowner $OBJOwner /t /c /q 2>&1 | Out-String -Stream -Width 9999
  3. $ICACLSResult = icacls "$OBJPath\*" /setowner $OBJOwner /t /c /q

Why they don't work

  1. Too much information, contains linebreaks
  2. Too much information, contains linebreaks
  3. Desired information still not in variable $ICACLSResult

Solution

  • The simplest method of keeping errors in the output is using the cmd Windows command line utility to redirect STDERR into STDOUT. Use quotes around the redirection operator to pass it to cmd:

    $log = cmd /c "2>&1" someutilityname /some /parameters
    

    For example:

    $log = cmd /c "2>&1" icacls "$OBJPath\*" /setowner $OBJOwner /t /c /q
    

    Now the $log variable is an array of output strings.