Como faço para detectar e pular arquivos bloqueados em um script do PowerShell?

1

Então, eu mesmo tenho um script do PowerShell que depois de muitas dores de cabeça eu comecei a trabalhar. Ii apaga arquivos que eu não quero mais e tudo está ótimo. Apenas um problema, ele irá excluir um arquivo se é aberto por outro programa ou não, o que é ruim. Meu código é o seguinte:

# Change the value $oldTime in order to set a limit for files to be deleted.
$oldTime = [int]30 # 30 days
foreach ($path in Get-Content "pathList.txt") {
        # Write information of what it is about to do
        Write-Host "Trying to delete files older than $oldTime days, in the folder $path" -ForegroundColor Green
        # deleting the old files
        Get-ChildItem $path -Recurse -filter "*EDI*" | WHERE {$_.LastWriteTime -le $(Get-Date).AddDays(-$oldTime)} | Remove-Item -Force

Eu só preciso de uma maneira para o script ver que um arquivo está aberto, pular o arquivo e seguir em frente. Estou executando o PowerShell 2.0 no Windows 7 SP1.

    
por user1210394 10.02.2015 / 21:52

1 resposta

1

Geralmente, tentar testar arquivos bloqueados ou não pode levar a todos os tipos de condições de corrida, porque o arquivo pode ficar bloqueado por outro thread / processo logo após a nossa verificação. E a verificação exige bloqueio próprio, a menos que isso não seja feito por meio da API Restart Manager, disponível apenas no Windows Vista (consulte esta resposta ) . Então você foi avisado.

Aqui está a função do PowerShell, que verificará se o arquivo está bloqueado ou não. Adaptado para o PowerShell desta questão: link

Copie e cole-o ou salve junto com o script como Test-IsFileLocked.ps1 e use o recurso de ponto para carregar:

$ScriptDir = Split-Path $script:MyInvocation.MyCommand.Path
. (Join-Path -Path $ScriptDir -ChildPath 'Test-IsFileLocked.ps1')

Em seguida, altere a última linha do seu script para:

Get-ChildItem $path -Recurse -filter "*EDI*" | WHERE {($_.LastWriteTime -le $(Get-Date).AddDays(-$oldTime)) -and !(Test-IsFileLocked -Files $_.FullName)} | Remove-Item -Force

função Test-IsFileLocked :

function Test-IsFileLocked
{
    [CmdletBinding()]
    Param
    (
        [Parameter(Mandatory = $true, ValueFromPipeline = $true)]
        [ValidateNotNullOrEmpty()]
        [string[]]$Files
    )

    Process
    {
        # Foreach loop to accept arrays either from pipeline or Files parameter
        foreach ($file in $Files)
        {
            $Locked = $false

            try
            {
                # Try to open file
                $Test = [System.IO.File]::Open($file, 'Open', 'ReadWrite', 'None')

                # Close file and dispose object if succeeded
                $Test.Close()
                $Test.Dispose()
            }
            catch
            {
                # File is locked!
                $Locked =  $true
            }

            # Write file status to pipeline
            $Locked
        }
    }
}
    
por 12.02.2015 / 17:24