2012-02-22 36 views
5

Estoy tratando de encontrar una solución que compruebe si un archivo está siendo utilizado por otro proceso. No quiero leer el contenido del archivo, ya que en un documento de 7 GB, esto podría demorar un tiempo. Actualmente estoy usando la función que se menciona a continuación, que no es ideal ya que el script tarda entre 5 y 10 minutos en recuperar un valor.Cómo comprobar si el archivo está siendo utilizado por otro proceso - Powershell

function checkFileStatus($filePath) 
{ 
    write-host (getDateTime) "[ACTION][FILECHECK] Checking if" $filePath "is locked" 

    if(Get-Content $filePath | select -First 1) 
    { 
     write-host (getDateTime) "[ACTION][FILEAVAILABLE]" $filePath 
     return $true 
    } 
    else 
    { 
     write-host (getDateTime) "[ACTION][FILELOCKED] $filePath is locked" 
     return $false 
    } 
} 

Cualquier ayuda sería muy apreciada

Respuesta

5

crea una función que resuelve el problema anterior:

function checkFileStatus($filePath) 
    { 
     write-host (getDateTime) "[ACTION][FILECHECK] Checking if" $filePath "is locked" 
     $fileInfo = New-Object System.IO.FileInfo $filePath 

     try 
     { 
      $fileStream = $fileInfo.Open([System.IO.FileMode]::Open, [System.IO.FileAccess]::Read, [System.IO.FileShare]::Read) 
      write-host (getDateTime) "[ACTION][FILEAVAILABLE]" $filePath 
      return $true 
     } 
     catch 
     { 
      write-host (getDateTime) "[ACTION][FILELOCKED] $filePath is locked" 
      return $false 
     } 
    } 
+0

Muchas gracias por su código. Es muy útil. Lo estoy usando para probar si un archivo en una ubicación de red compartida está disponible para su uso. Cada pocos días cargan un nuevo archivo grande en esa ubicación (que tarda unas horas en cargarse) y quiero asegurarme de que la carga finalice para poder copiar y descargar ese archivo de manera segura a mi máquina local. ¿Ves algún defecto en mi concepto? – FrozenLand

+0

¿Hay alguna razón por la que esto no llame '$ fileStream.Dispose()' antes de salir? – user2426679

+0

@ user2426679 He leído que el recolector de basura se encargará de eso, a menos que esté creando demasiados objetos dentro de un cierto período de tiempo –

1

Comprobar este script en poschcode.org:

filter Test-FileLock { 
    if ($args[0]) {$filepath = gi $(Resolve-Path $args[0]) -Force} else {$filepath = gi $_.fullname -Force} 
    if ($filepath.psiscontainer) {return} 
    $locked = $false 
    trap { 
     Set-Variable -name locked -value $true -scope 1 
     continue 
    } 
    $inputStream = New-Object system.IO.StreamReader $filepath 
    if ($inputStream) {$inputStream.Close()} 
    @{$filepath = $locked} 
} 
+0

FYI eso no es un enlace PoshCode. –

+0

URL de pasta fija, incorrecta –

+0

Gracias, con la ayuda del enlace, creé una nueva función que hace lo que se requiere. – user983965

0

ya que no desea leer el archivo, yo recomendaría usar una utilidad como Sysinternals Handle .exe, que escupirá todos los identificadores abiertos para un proceso. Puede descargar Handle.exe desde aquí:

http://technet.microsoft.com/en-us/sysinternals/bb896655

Puede ejecutar Handle.exe sin ningún argumento, y ha de devolver todos los identificadores de archivos abiertos. Puede analizar el resultado si es necesario o simplemente hacer coincidir el resultado con la ruta completa del archivo.

3

La función que utilizo para comprobar si un archivo está bloqueado o no:

 
function IsFileLocked([string]$filePath){ 
    Rename-Item $filePath $filePath -ErrorVariable errs -ErrorAction SilentlyContinue 
    return ($errs.Count -ne 0) 
} 
-1
function IsFileAccessible([String] $FullFileName) 
{ 
    [Boolean] $IsAccessible = $false 

    try 
    { 
    Rename-Item $FullFileName $FullFileName -ErrorVariable LockError -ErrorAction Stop 
    $IsAccessible = $true 
    } 
    catch 
    { 
    $IsAccessible = $false 
    } 
    return $IsAccessible 
} 
+0

Agregue algunos comentarios a su respuesta. – HDJEMAI

Cuestiones relacionadas