public/Watch-LimitFileSize.ps1
function Watch-LimitFileSize { <# .SYNOPSIS Creates or updates a scheduled task to monitor one or more files. .DESCRIPTION This function creates a Windows scheduled task named "WatchLimitFileSize" that runs the Set-LimitFileSize cmdlet on one or more specified paths. It also applies strict ACLs to these files/folders if the Set-RestrictiveACL module is available. The task is started immediately after being created or updated. .PARAMETER Path Array of strings containing one or more file or folder paths to monitor. Examples: 'C:\logs\app.log', 'D:\data\config.txt'. .PARAMETER MaxSize The maximum size the file is allowed to reach before triggering a trimming operation. The value must be a number followed optionally by a unit : - Use "Ko" for kilooctets (e.g., "100000Ko") - Use "Mo" for megaoctets (e.g., "150Mo") - If no unit is specified, kilooctets are assumed by default (e.g., "200" means "200Ko"). Default: "256Ko" .PARAMETER VerboseLevel Controls the script's verbosity level : - "Disabled" : no console output. - "Normal" : minimal output. - "Debug" : displays details such as initial and final file size. .EXAMPLE Watch-LimitFileSize -Path "C:\Logs\app.log" Creates the scheduled task to monitor a single file. .EXAMPLE Watch-LimitFileSize -Path "C:\Logs\app1.log", "C:\Logs\app2.log" Creates the scheduled task to monitor multiple files. .NOTES Version : 1.0.0 Author : Frederic PETIT Created : 2025-05-22 Revised : 2025-05-31 Compatibility: PowerShell 5+ #> [CmdletBinding(SupportsShouldProcess = $true)] Param ( [Parameter(Mandatory=$true)][string[]]$Path, [Parameter(Mandatory=$false)][string]$MaxSize = "256Ko", [Parameter(Mandatory=$false)][ValidateSet("Disabled", "Debug")][string]$VerboseLevel = "Disabled" ) # Définition de la tâche. $Task = @{ Name = "WatchLimitFileSize" Path = "$env:windir\System32\Tasks" Xml = @" <?xml version="1.0" encoding="UTF-16"?> <Task version="1.4" xmlns="http://schemas.microsoft.com/windows/2004/02/mit/task"> <RegistrationInfo> <Date>2025-04-04T00:00:00</Date> <Author>Administrateur</Author> <URI>\WatchLimitFileSize</URI> </RegistrationInfo> <Triggers> <BootTrigger> <Enabled>true</Enabled> </BootTrigger> <TimeTrigger> <StartBoundary>2025-01-01T07:00:00</StartBoundary> <Enabled>true</Enabled> </TimeTrigger> </Triggers> <Principals> <Principal id="Author"> <UserId>S-1-5-18</UserId> <RunLevel>HighestAvailable</RunLevel> </Principal> </Principals> <Settings> <MultipleInstancesPolicy>Queue</MultipleInstancesPolicy> <DisallowStartIfOnBatteries>false</DisallowStartIfOnBatteries> <StopIfGoingOnBatteries>true</StopIfGoingOnBatteries> <AllowHardTerminate>true</AllowHardTerminate> <StartWhenAvailable>false</StartWhenAvailable> <RunOnlyIfNetworkAvailable>false</RunOnlyIfNetworkAvailable> <IdleSettings> <StopOnIdleEnd>true</StopOnIdleEnd> <RestartOnIdle>false</RestartOnIdle> </IdleSettings> <AllowStartOnDemand>true</AllowStartOnDemand> <Enabled>true</Enabled> <Hidden>false</Hidden> <RunOnlyIfIdle>false</RunOnlyIfIdle> <DisallowStartOnRemoteAppSession>false</DisallowStartOnRemoteAppSession> <UseUnifiedSchedulingEngine>true</UseUnifiedSchedulingEngine> <WakeToRun>true</WakeToRun> <ExecutionTimeLimit>PT5M</ExecutionTimeLimit> <Priority>7</Priority> </Settings> </Task> "@ } # Convertir les chemins bruts en chemins absolus, pour éviter les erreurs de contexte. try { $ResolvedPaths = Resolve-Path -LiteralPath $Path | Select-Object -ExpandProperty Path; } catch { throw "Error resolving paths : $_"; } # Préparer chaque chemin entre quotes pour usage inline dans un tableau PowerShell. $joined = ($ResolvedPaths | ForEach-Object { "'$_'" }) -join ','; # Créer une commande complète qui appelle Set-LimitFileSize avec les bons chemins. $cmd = "Import-Module LimitFileSize; Set-LimitFileSize -Path @($joined) -MaxSize $MaxSize"; $argList = "-ExecutionPolicy Bypass -Command `"$cmd`""; # Enregistrer ou écraser la tâche planifiée, puis remplacer son action par celle attendue. try { $RegisteredTask = Register-ScheduledTask -TaskName $Task.Name -Xml $Task.Xml -Force; } catch { throw "Error registering task : $_"; } $Definition = $RegisteredTask.Definition; $Definition.Actions.Clear(); $Definition.Actions.Add((New-ScheduledTaskAction -Execute 'powershell.exe' -Argument $argList)); $RegisteredTask.RegisterChanges(); # Appliquer les ACL strictes sur chaque chemin, si la commande est disponible. if (Get-Command -Name Set-RestrictiveACL -ErrorAction SilentlyContinue) { foreach ($resolved in $ResolvedPaths) { try { Set-RestrictiveACL -Path $resolved; } catch { if ($VerboseLevel -eq "Debug") { Write-Warning "Unable to perform Set-RestrictiveACL on '$resolved' : $_"; } } } } # Vérifier que la tâche a bien été enregistrée puis la démarrer immédiatement. try { if (Check-ScheduledTask -Name $Task.Name) { if ($VerboseLevel -eq "Debug") { Write-Host "Task '$Task.Name' OK" -ForegroundColor Green; } try { Start-ScheduledTask -TaskName $Task.Name; if ($VerboseLevel -eq "Debug") { Write-Host "Task '$Task.Name' EXEC." -ForegroundColor Green; } } catch { if ($VerboseLevel -eq "Debug") { Write-Warning "Impossible to start '$($Task.Name)' : $_"; } } } else { if ($VerboseLevel -eq "Debug") { Write-Warning "Task '$($Task.Name)' not found after creation."; } } } catch { if ($VerboseLevel -eq "Debug") { Write-Warning "Task '$($Task.Name)' verification failed : $_"; } } } |