2

My PowerShell script just checks multiple servers to make sure the input* and output* directories are clear of any files.

I'm simply trying to output to console the results of a GCI call prior to throwing an error message. However, when I uncomment the "throw" line, the $inputFiles and $outputFiles no longer output to the console. Below is the code:

$allServers = @(
    "server1.com",
    "server2.com")

foreach ($server in $allServers) {

    $inputFiles = Get-ChildItem -Path "\\$server\C$\jobs\statements\input*\" -Recurse | Where-Object {! $_.PSIsContainer } | Select FullName
    $outputFiles = Get-ChildItem -Path "\\$server\C$\jobs\statements\output*\" -Recurse | Where-Object {! $_.PSIsContainer } | Select FullName

    if ($inputFiles -eq $NULL -and $outputFiles -eq $NULL) {
    
        Write-Host "Environment is ready for statement processing."
    }

    else {

        Write-Host "Environment is NOT ready for statement processing."
        Write-Host "The following files exist in input/output: `n"
        $inputFiles
        $outputFiles
        #Throw "Files exist in input/output. See above for details."
    }
}

Below is the console output:

Environment is NOT ready for statement processing.
The following files exist in input/output: 


Environment is NOT ready for statement processing.
The following files exist in input/output: 

FullName                                                                
--------                                                                
\\server1.com\C$\jobs\statements\input\asdasd.txt         
\\server1.com\C$\jobs\statements\input_254\asdasd.txt     
\\server1.com\C$\jobs\statements\input_test\asdasd.txt    
\\server2.com\C$\jobs\statements\input\CUSSTAT10302021.245
\\server2.com\C$\jobs\statements\input\CUSSTAT11312021    
\\server2.com\C$\jobs\statements\input\CUSSTAT11312021.zip

And below is the console output when I uncomment the "throw" line:

Environment is NOT ready for statement processing.
The following files exist in input/output: 


Files exist in input/output. See above for details.
At C:\jobs\statements\bin\Statements-EnvironmentCheck.ps1:47 char:9
+         Throw "Files exist in input/output. See above for details."
+         ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : OperationStopped: (Files exist in ...ve for details.:String) [], RuntimeException
    + FullyQualifiedErrorId : Files exist in input/output. See above for details.

I know I have some error output cleanup to perform in order to include all the servers that might have files present, but please ignore that for now.

Oshua
  • 23
  • 5
  • Why bother with Throw just use Write-Host? – RetiredGeek Apr 19 '22 at 21:56
  • 1
    you are mixing direct-to-screen [`write-host`] with indirect-to-screen [your bare variables] actions. i presume the `throw` is cutting the indirect screen output off when it is triggered. – Lee_Dailey Apr 19 '22 at 22:10
  • 1
    I think any command in the same position as the throw would cause the variable value not to be printed to screen. It prints to screen because it's the last value in the block. I think it's better style to use `Write-Error "error message" -ErrorAction Stop` instead of using `throw`. Write-Error also has other parameters that are useful for generating exceptions like -TargetObject. – Todd Apr 20 '22 at 01:26

1 Answers1

1

What you're experiencing is explained in this answer and this answer, basically you need to implement Out-Host \ Out-Default:

$inputFiles, $outputFiles | Out-Host # Should fix the problem
# possibly `throw` might require this too
throw "Files exist in input/output. See above for details." | Out-Host

However, I feel is worth showing you a better way to approach your code, returning a unified array of objects which you can filter, sort and export.

$allServers = @(
    "server1.com"
    "server2.com"
)

$result = foreach ($server in $allServers) {
    # use `-File` instead of `! $_.PSIsContainer`
    $out = @{
        in  = Get-ChildItem "\\$server\C$\jobs\statements\input*\" -Recurse -File
        out = Get-ChildItem "\\$server\C$\jobs\statements\output*\" -Recurse -File
    }

    # if $out['in'] and $out['out'] are `$null`, Ready is `$true`
    [pscustomobject]@{
        Ready  = -not($out['in'] -or $out['out'])
        Server = $server
        Files  = $out
    }
}

Now, if you want to see which servers are Ready (no files in input and output):

$result.where{ $_.Ready }

And if you want to see which servers are not Ready, and have a list of the files:

$result.where{ -not $_.Ready }.foreach{
    foreach($file in $_.Files.PSBase.Values.FullName) {
        [pscustomobject]@{
            Server = $_.Server
            Files  = $file
        }
    }
}
Santiago Squarzon
  • 41,465
  • 5
  • 14
  • 37