Come posso rilevare e saltare i file bloccati in uno script di PowerShell?


1

Quindi ho uno script PowerShell che dopo molti mal di testa ho iniziato a lavorare. Ii elimina i file che non desidero più e tutto è fantastico. Solo un problema, eliminerà un file sia che sia aperto da un altro programma o meno, il che è male. Il mio codice è il seguente:

# 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

Ho solo bisogno di un modo per lo script per vedere che un file è aperto, saltare detto file e andare avanti. Sto eseguendo PowerShell 2.0 su Windows 7 SP1.


Sei sicuro che i file siano bloccati quando sono aperti? Spesso i programmi eseguono una copia temporanea (o semplicemente la caricano completamente in memoria) e quindi rilasciano il blocco dei file in modo che altri possano accedervi. Quando salvi il prossimo, bloccherà il file abbastanza a lungo da scaricarlo di nuovo. Quindi, in sostanza, potrebbe non esserci alcun modo per determinare se il file è in uso o meno, a seconda del programma che lo ha aperto.
Ƭᴇcʜιᴇ007,

Ad esempio stavo testando su una cartella che conteneva MP3. Quando ho cercato di eliminare tutto in quella cartella, ha eliminato tutto tranne quel file che stavo ascoltando, ma errori di gioco. Diceva che veniva usato da un altro processo. Ho solo bisogno di un modo per saltare quei file nel caso in cui mi imbatto in quel problema. Ma verrà utilizzato principalmente per eliminare i file txt.
user1210394

Risposte:


1

Generalmente, provare a testare il file è bloccato o meno può portare a tutti i tipi di condizioni di competizione, perché il file potrebbe essere bloccato da un altro thread / processo subito dopo il nostro controllo. E il controllo richiede il blocco stesso, a meno che non venga eseguito tramite l'API Restart Manager che è disponibile solo da Windows Vista (vedi questa risposta ). Quindi sei stato avvisato.

Ecco la funzione di PowerShell, che controlla se il file è bloccato o meno. Adattato a PowerShell da questa domanda: https://stackoverflow.com/questions/876473/is-there-a-way-to-check-if-a-file-is-in-use

Copialo incolla o salva insieme allo script come Test-IsFileLocked.ps1e usa il dot-sourcing per caricare:

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

E poi cambia l'ultima riga del tuo script in:

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

Test-IsFileLocked funzione stessa:

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
        }
    }
}
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.