0

I'm creating a script using jobs to search through directories and delete specific file extensions, then write to a log file.

When running the script without creating a log file, the output is clean and compact. However, when I run the same script after creating a log file, the terminal output changes to a fuller, less compact view (even when the rest of the script doesn't interact with the file)

I've tried creating the file in a separate function, but the same behaviour occurs.

I've also tried steering away from Out-File using a Write-Log function from Ben Newton under this thread, but this still doesn't change the behaviour.

Function Clean-DrivesParallel {
    Param(
            [Parameter(Mandatory=$true, Position=0)]
            [string] $Path,
            [Parameter(Mandatory=$true, Position=1)]
            [string] $FileType,
            [Parameter(Mandatory=$false, Position=2)]
            [switch] $Test
        )
    $ErrorActionPreference = 'SilentlyContinue'
    CreateLogFile
    $logfile = "H:\Scripts\Log Files\Drive Clean-Up.log"
    $jobs = @()
    $("Drive Clean-up log file || $date || $path") | Out-File $logfile -append
    Get-ChildItem -Directory $Path | % {
        $SubPath = $_.FullName
        Write-Log -Message $("Job assigned to $SubPath") -logfile $logfile
        $id = [System.Guid]::NewGuid()
        $jobs += $id   
        Start-Job -Name $id -ArgumentList $SubPath,$FileType,$Test -ScriptBlock {
            Get-ChildItem $($args[0]) -Include *$($args[1]) -Recurse | % {
                If($($args[2]) -eq $True){
                    Remove-Item $_.FullName -WhatIF
                }
                Else {
                    Remove-Item $_.FullName
                }
            }
        }
    }
    "--------------------------------------------------------" | Out-File $logfile -append
    While (Get-Job -State "Running") {
        Start-Sleep 1 
    }
    write-host "Jobs completed, getting output"

    Foreach($job in $jobs) {
        Write-Log -Message (Receive-Job -Name $job) -logfile $logfile
    }
    "════════════════════════════════════════════════════════" | Out-File $logfile -append
    Remove-Job *
    Write-Host $("Jobs Completed. Log file written to $logfile")
    $ErrorActionPreference = 'Continue'
}


Function CreateLogFile {
    $date = get-date -Format "dd-MM-yyyy HH-mm"
    $logname = "Drive Clean-up Log " + $date + ".log"
    $logpath = "H:\Scripts\Log Files\"
    $logfile = $logpath + $logname
    New-Item -Path $logpath -Name $logname -ItemType "file"
}


Function Write-Log {
    [CmdletBinding()]
    Param(
    [Parameter(Mandatory=$False)]
    [ValidateSet("INFO","WARN","ERROR","FATAL","DEBUG")]
    [String]
    $Level = "INFO",

    [Parameter(Mandatory=$True)]
    [string]
    $Message,

    [Parameter(Mandatory=$False)]
    [string]
    $logfile
    )

    $Stamp = (Get-Date).toString("yyyy/MM/dd HH:mm:ss")
    $Line = "$Stamp $Level $Message"
    If($logfile) {
        Add-Content $logfile -Value $Line
    }
    Else {
        Write-Output $Line
    }
}

I'm aiming to have a single log file created from each script, but when running large clean-ups, it looks messy.

I've had a look but can't find any posts about this. Is there something I'm missing?

Any help would be greatly appreciated!

Thank you

Edit:

Output when file is not created (for each job):

Id     Name            PSJobTypeName   State         HasMoreData     Location             Command
--     ----            -------------   -----         -----------     --------             -------
627    3a8c6df6-f4b... BackgroundJob   Running       True            localhost            ...
629    65afee11-0b3... BackgroundJob   Running       True            localhost            ...
631    a8b50789-00e... BackgroundJob   Running       True            localhost            ...
633    1af20d55-98e... BackgroundJob   Running       True            localhost            ...
635    6d34bec1-2a3... BackgroundJob   Running       True            localhost            ...
637    65650674-304... BackgroundJob   Running       True            localhost            ...
639    a15031b8-3f4... BackgroundJob   Running       True            localhost            ...
641    5dfc875e-c00... BackgroundJob   Running       True            localhost            ...

Output when file is created (for each job):

Finished      : System.Threading.ManualResetEvent  
InstanceId    : c8c05aa9-c895-4776-80c0-58eeee8daa15  
Id            : 621  
Name          : 1253bed7-ff3a-4e6d-9e1b-5676d56e92ee  
ChildJobs     : {Job622}  
PSBeginTime   : 27/09/2021 22:13:29  
PSEndTime     :  
PSJobTypeName : BackgroundJob  
Output        : {}  
Error         : {}  
Progress      : {}  
Verbose       : {}  
Debug         : {}  
Warning       : {}  
State         : Running  


HasMoreData   : True  
StatusMessage :  
Location      : localhost  
Command       :  
                            Get-ChildItem $($args[0]) -Include *$($args[1]) -Recurse | % {  
                                If($($args[2]) -eq $True){  
                                    Remove-Item $_.FullName -WhatIF  
                                }  
                                Else {  
                                    Remove-Item $_.FullName  
                                }  
                            }  
  • 2
    `$null = CreateLogFile` – Mathias R. Jessen Sep 27 '21 at 22:32
  • 1
    In short: any output - be it from a PowerShell command or a .NET method call - that is neither captured in a variable nor redirected (sent through the pipeline or to a file) is _implicitly output_ from a script or function. Here, `New-Item` is the likely culprit. To simply _discard_ such output, use `$null = ...`. If you don't discard such output, it becomes part of a script or function's "return value" (stream of output objects). See [this answer](https://stackoverflow.com/a/55665963/45375) to the linked duplicate. – mklement0 Sep 27 '21 at 23:25
  • Aw man, it's that basic? Seems I have much more to learn with PowerShell. Thank you both! – Battery_Smooth Sep 28 '21 at 08:22

0 Answers0