none
Cortar uso de un archivo en Pwshell RRS feed

  • Pregunta

  • Tengo estas tres lineas de comando:

     

     

    rename-item -path E:\108_2\1851\1852\DP08F1-AA00-G0100-BD001_0001_r01.DWG -newname DP08F1-AA00-G0100-BD001_0001.dwg

     

     

    Copy-FilestoSP -LocalPath "E:\108_2\1851\1852\DP08F1-AA00-G0100-BD001_0001.dwg" -SiteUrl "http://srvshpw/Inicio.aspx" -Library "BASICA" -ManifestFilePath "E:\TEST\XML\DP08F1-AA00-G0100-BD001.xml"  -Overwrite


     

    remove-item E:\108_2\1851\1852\DP08F1-AA00-G0100-BD001_0001.dwg -force

     

     

     

    Basicamente lo que pretendo es tomaer un archivo cambiar su nombre, subirlo a sharepoint y borrar el archivo del disco duro, mi problema esta en un error que manda al intentar borrar el archivo porque dice que powershell lo esta usando, como puedo terminar el handle que retiene el archivo y de esta forma lograr que se ejecute sin error el comando remove

     

     

     

     

     

    jueves, 24 de febrero de 2011 1:02

Respuestas

  • Desconozco cómo trabaja ese script que usas (Copy-FilestoSP) pero por lo que comentas, podría ser que subiera al servidor los ficheros en backgrund, de manera que devuelve el control a PowerShell sin haber terminado de subirlos, de ahí el que estén bloqueados. Si esto es así, podrías crearte una función que comprobase si está o no bloqueado el fichero, una cosa así:

    Function Test-FileLock([string]$FilePath)
    {
      # Iniciamos la variable de devolucion como False
      $Devolucion = $False
      
      # Para saber si está o no bloqueado intentaremos obtener el contenido del
      # fichero; si está bloqueado se producirá un error. Este error es un error
      # que no interrumpe, por lo que no sería posible interceptarlo con un Try;
      # para evitar esto, cambiamos la acción a realizar con los errores que no
      # interrumpen para que sí lo hagan, de manera que sí funcionará el Try
      
      # Recogemos el valor actual de la preferencia de acción con los errores que
      # no interrumpen
      $AccionDeError = $ErrorActionPreference
      # Hacemos que sí interrumpan dichos errores
      $ErrorActionPreference = "Stop"
      
      # Intentamos obtener el contenido del fichero, enviando el contenido al
      # limbo :o) (no queremos que aparezca por pantalla)
      Try
      {
        Get-Content $FilePath | Out-Null
      }
      # Si se produce error es que está bloqueado y por tanto marcamos la
      # devolución como True
      Catch
      {
        $Devolucion = $true
      }
      
      # Restauramos la preferencia de acción ante errores que no interrumpen
      $ErrorActionPreference = $AccionDeError
      
      # Realizamos la devolución
      $Devolucion
    }

    Entonces en tu Script, antes de intentar borrar el fichero, debería testear si está o no bloqueado, y si lo está volver a intentar pasado un tiempo; pongamos que una cosa así:

    # si el fichero está bloqueado, espera 5 segundos y vuelve a revisar si está o
    # no bloqueado, así hasta que no lo esté
    While((Test-FileLock E:\108_2\1851\1852\DP08F1-AA00-G0100-BD001_0001.dwg) `
                                       -eq $true)
    {
      Start-Sleep -Seconds 5
    }
    Remove-Item E:\108_2\1851\1852\DP08F1-AA00-G0100-BD001_0001.dwg -force
    

    Con este enfoque, tu script quedaría así:

    Function Test-FileLock([string]$FilePath)
    {
      # Iniciamos la variable de devolucion como False
      $Devolucion = $False
      
      # Para saber si está o no bloqueado intentaremos obtener el contenido del
      # fichero; si está bloqueado se producirá un error. Este error es un error
      # que no interrumpe, por lo que no sería posible interceptarlo con un Try;
      # para evitar esto, cambiamos la acción a realizar con los errores que no
      # interrumpen para que sí lo hagan, de manera que sí funcionará el Try
      
      # Recogemos el valor actual de la preferencia de acción con los errores que
      # no interrumpen
      $AccionDeError = $ErrorActionPreference
      # Hacemos que sí interrumpan dichos errores
      $ErrorActionPreference = "Stop"
      
      # Intentamos obtener el contenido del fichero, enviando el contenido al
      # limbo :o) (no queremos que aparezca por pantalla)
      Try
      {
        Get-Content $FilePath | Out-Null
      }
      # Si se produce error es que está bloqueado y por tanto marcamos la
      # devolución como True
      Catch
      {
        $Devolucion = $true
      }
      
      # Restauramos la preferencia de acción ante errores que no interrumpen
      $ErrorActionPreference = $AccionDeError
      
      # Realizamos la devolución
      $Devolucion
    }
    
    Rename-Item -Path E:\108_2\1851\1852\DP08F1-AA00-G0100-BD001_0001_r01.DWG `
          -NewName DP08F1-AA00-G0100-BD001_0001.dwg
    
    Copy-FilestoSP -LocalPath "E:\108_2\1851\1852\DP08F1-AA00-G0100-BD001_0001.dwg"`
            -SiteUrl "http://srvshpw/Inicio.aspx" -Library "BASICA" `
            -ManifestFilePath "E:\TEST\XML\DP08F1-AA00-G0100-BD001.xml" `
            -Overwrite
    # si el fichero está bloqueado, espera 5 segundos y vuelve a revisar si está o
    # no bloqueado, así hasta que no lo esté
    While((Test-FileLock E:\108_2\1851\1852\DP08F1-AA00-G0100-BD001_0001.dwg) `
                                       -eq $true)
    {
      Start-Sleep -Seconds 5
    }
    Remove-Item E:\108_2\1851\1852\DP08F1-AA00-G0100-BD001_0001.dwg -force
    

    Si lo que quieres es identificar el proceso que bloquea a un archivo, PowerShell directamente no te lo puede decir, debes usar otras herramientas, como Handle de SysInternals:

    http://stackoverflow.com/questions/958123/powershell-script-to-check-application-thats-locking-a-file


    Un saludo

    Fernando Reyes [MS MVP]
    MCSA 2000/2003
    MCSE 2000/2003
    MCITP EnterpriseAdministrator
    Web: http://freyes.svetlian.com
    Blog: http://urpiano.wordpress.com
    RSS: http://urpiano.wordpress.com/feed/
    freyes.champú@champú.mvps.org
    (Aclárate la cabeza si quieres escribirme)
    jueves, 24 de febrero de 2011 10:20
    Moderador
  • Pues no te se decir, eso depende de porqué el fichero está bloqueado y si eso implica que pueda quedar siempre bloqueado. Podrías bajarte handle y mirar qué es lo que tiene el fichero bloqueado y si lo termina liberando. Si, como me imagino, tu preocupación es que con un enfoque como el que te he dado se pueda producir un bucle infinito, podrías limitar en el tiempo el bucle, es decir, guardar la hora en la que comienza el bucle y en el control de salida del mismo establecer una condición, a parte de la de encontrar liberado el fichero, que salga del bucle pasado el tiempo que consideres más conveniente; y si la causa de esta salida de bucle es el excesivo tiempo no eliminar el fichero (guardando en un log que no ha sido liberado) o matar el proceso que lo tiene bloqueado y después liberarlo. Pero esto último tiene el peligro de que sea necesario que el proceso lo esté bloqueando (por ejemplo, que lo está todavía subiendo), así que lo mejor sería que identificases porqué está bloqueado el fichero y una vez conocida la causa decidir el mejor enfoque del script para proceder; yo creo que el primer enfoque que te he dado debería funcionar, pues imagino que el problema, como te dije en la anterior respuesta, es que el fichero se está subiendo en background y por tanto el script intenta borrarlo cuando todavía está en uso.

    Para controlar el tiempo que está el script en el bucle, puedes hacer algo así:

    # Guardamos la hora actual
    $HoraInicio = Get-Date
    $ExcesivoTiempo = $False
    # si el fichero está bloqueado, espera 5 segundos y vuelve a revisar si está o
    # no bloqueado, así hasta que no lo esté o que hayan transcurrido 5 minutos
    While(((Test-FileLock E:\108_2\1851\1852\DP08F1-AA00-G0100-BD001_0001.dwg) `
                                      -eq $true) `
        -And $ExcesivoTiempo -eq $False)
    {
      Start-Sleep -Seconds 5
      $ExcesivoTiempo = (New-TimeSpan -Start (Get-Date) `
                      -End ($HoraInicio)).Minutes -gt 4
    }
    If($ExcesivoTiempo -eq $false)
    {
      Remove-Item E:\108_2\1851\1852\DP08F1-AA00-G0100-BD001_0001.dwg -force
    }
    Else
    {
      "El Fichero E:\108_2\1851\1852\DP08F1-AA00-G0100-BD001_0001.dwg no se borró
    por estar bloqueado" >> .\LogSubidaSP.log
    }

     


    Un saludo

    Fernando Reyes [MS MVP]
    MCSA 2000/2003
    MCSE 2000/2003
    MCITP EnterpriseAdministrator
    Web: http://freyes.svetlian.com
    Blog: http://urpiano.wordpress.com
    RSS: http://urpiano.wordpress.com/feed/
    freyes.champú@champú.mvps.org
    (Aclárate la cabeza si quieres escribirme)
    viernes, 25 de febrero de 2011 8:12
    Moderador

Todas las respuestas

  • Desconozco cómo trabaja ese script que usas (Copy-FilestoSP) pero por lo que comentas, podría ser que subiera al servidor los ficheros en backgrund, de manera que devuelve el control a PowerShell sin haber terminado de subirlos, de ahí el que estén bloqueados. Si esto es así, podrías crearte una función que comprobase si está o no bloqueado el fichero, una cosa así:

    Function Test-FileLock([string]$FilePath)
    {
      # Iniciamos la variable de devolucion como False
      $Devolucion = $False
      
      # Para saber si está o no bloqueado intentaremos obtener el contenido del
      # fichero; si está bloqueado se producirá un error. Este error es un error
      # que no interrumpe, por lo que no sería posible interceptarlo con un Try;
      # para evitar esto, cambiamos la acción a realizar con los errores que no
      # interrumpen para que sí lo hagan, de manera que sí funcionará el Try
      
      # Recogemos el valor actual de la preferencia de acción con los errores que
      # no interrumpen
      $AccionDeError = $ErrorActionPreference
      # Hacemos que sí interrumpan dichos errores
      $ErrorActionPreference = "Stop"
      
      # Intentamos obtener el contenido del fichero, enviando el contenido al
      # limbo :o) (no queremos que aparezca por pantalla)
      Try
      {
        Get-Content $FilePath | Out-Null
      }
      # Si se produce error es que está bloqueado y por tanto marcamos la
      # devolución como True
      Catch
      {
        $Devolucion = $true
      }
      
      # Restauramos la preferencia de acción ante errores que no interrumpen
      $ErrorActionPreference = $AccionDeError
      
      # Realizamos la devolución
      $Devolucion
    }

    Entonces en tu Script, antes de intentar borrar el fichero, debería testear si está o no bloqueado, y si lo está volver a intentar pasado un tiempo; pongamos que una cosa así:

    # si el fichero está bloqueado, espera 5 segundos y vuelve a revisar si está o
    # no bloqueado, así hasta que no lo esté
    While((Test-FileLock E:\108_2\1851\1852\DP08F1-AA00-G0100-BD001_0001.dwg) `
                                       -eq $true)
    {
      Start-Sleep -Seconds 5
    }
    Remove-Item E:\108_2\1851\1852\DP08F1-AA00-G0100-BD001_0001.dwg -force
    

    Con este enfoque, tu script quedaría así:

    Function Test-FileLock([string]$FilePath)
    {
      # Iniciamos la variable de devolucion como False
      $Devolucion = $False
      
      # Para saber si está o no bloqueado intentaremos obtener el contenido del
      # fichero; si está bloqueado se producirá un error. Este error es un error
      # que no interrumpe, por lo que no sería posible interceptarlo con un Try;
      # para evitar esto, cambiamos la acción a realizar con los errores que no
      # interrumpen para que sí lo hagan, de manera que sí funcionará el Try
      
      # Recogemos el valor actual de la preferencia de acción con los errores que
      # no interrumpen
      $AccionDeError = $ErrorActionPreference
      # Hacemos que sí interrumpan dichos errores
      $ErrorActionPreference = "Stop"
      
      # Intentamos obtener el contenido del fichero, enviando el contenido al
      # limbo :o) (no queremos que aparezca por pantalla)
      Try
      {
        Get-Content $FilePath | Out-Null
      }
      # Si se produce error es que está bloqueado y por tanto marcamos la
      # devolución como True
      Catch
      {
        $Devolucion = $true
      }
      
      # Restauramos la preferencia de acción ante errores que no interrumpen
      $ErrorActionPreference = $AccionDeError
      
      # Realizamos la devolución
      $Devolucion
    }
    
    Rename-Item -Path E:\108_2\1851\1852\DP08F1-AA00-G0100-BD001_0001_r01.DWG `
          -NewName DP08F1-AA00-G0100-BD001_0001.dwg
    
    Copy-FilestoSP -LocalPath "E:\108_2\1851\1852\DP08F1-AA00-G0100-BD001_0001.dwg"`
            -SiteUrl "http://srvshpw/Inicio.aspx" -Library "BASICA" `
            -ManifestFilePath "E:\TEST\XML\DP08F1-AA00-G0100-BD001.xml" `
            -Overwrite
    # si el fichero está bloqueado, espera 5 segundos y vuelve a revisar si está o
    # no bloqueado, así hasta que no lo esté
    While((Test-FileLock E:\108_2\1851\1852\DP08F1-AA00-G0100-BD001_0001.dwg) `
                                       -eq $true)
    {
      Start-Sleep -Seconds 5
    }
    Remove-Item E:\108_2\1851\1852\DP08F1-AA00-G0100-BD001_0001.dwg -force
    

    Si lo que quieres es identificar el proceso que bloquea a un archivo, PowerShell directamente no te lo puede decir, debes usar otras herramientas, como Handle de SysInternals:

    http://stackoverflow.com/questions/958123/powershell-script-to-check-application-thats-locking-a-file


    Un saludo

    Fernando Reyes [MS MVP]
    MCSA 2000/2003
    MCSE 2000/2003
    MCITP EnterpriseAdministrator
    Web: http://freyes.svetlian.com
    Blog: http://urpiano.wordpress.com
    RSS: http://urpiano.wordpress.com/feed/
    freyes.champú@champú.mvps.org
    (Aclárate la cabeza si quieres escribirme)
    jueves, 24 de febrero de 2011 10:20
    Moderador
  • Muchas gracias lo pondre en practica cuanto antes y te comento los resultados!!! solo una pregunta es posible teoricamente que en algun momento del proceso por cualquier circunstancia nunca se libere el archivo!!!?

    Saludos

    viernes, 25 de febrero de 2011 0:31
  • Pues no te se decir, eso depende de porqué el fichero está bloqueado y si eso implica que pueda quedar siempre bloqueado. Podrías bajarte handle y mirar qué es lo que tiene el fichero bloqueado y si lo termina liberando. Si, como me imagino, tu preocupación es que con un enfoque como el que te he dado se pueda producir un bucle infinito, podrías limitar en el tiempo el bucle, es decir, guardar la hora en la que comienza el bucle y en el control de salida del mismo establecer una condición, a parte de la de encontrar liberado el fichero, que salga del bucle pasado el tiempo que consideres más conveniente; y si la causa de esta salida de bucle es el excesivo tiempo no eliminar el fichero (guardando en un log que no ha sido liberado) o matar el proceso que lo tiene bloqueado y después liberarlo. Pero esto último tiene el peligro de que sea necesario que el proceso lo esté bloqueando (por ejemplo, que lo está todavía subiendo), así que lo mejor sería que identificases porqué está bloqueado el fichero y una vez conocida la causa decidir el mejor enfoque del script para proceder; yo creo que el primer enfoque que te he dado debería funcionar, pues imagino que el problema, como te dije en la anterior respuesta, es que el fichero se está subiendo en background y por tanto el script intenta borrarlo cuando todavía está en uso.

    Para controlar el tiempo que está el script en el bucle, puedes hacer algo así:

    # Guardamos la hora actual
    $HoraInicio = Get-Date
    $ExcesivoTiempo = $False
    # si el fichero está bloqueado, espera 5 segundos y vuelve a revisar si está o
    # no bloqueado, así hasta que no lo esté o que hayan transcurrido 5 minutos
    While(((Test-FileLock E:\108_2\1851\1852\DP08F1-AA00-G0100-BD001_0001.dwg) `
                                      -eq $true) `
        -And $ExcesivoTiempo -eq $False)
    {
      Start-Sleep -Seconds 5
      $ExcesivoTiempo = (New-TimeSpan -Start (Get-Date) `
                      -End ($HoraInicio)).Minutes -gt 4
    }
    If($ExcesivoTiempo -eq $false)
    {
      Remove-Item E:\108_2\1851\1852\DP08F1-AA00-G0100-BD001_0001.dwg -force
    }
    Else
    {
      "El Fichero E:\108_2\1851\1852\DP08F1-AA00-G0100-BD001_0001.dwg no se borró
    por estar bloqueado" >> .\LogSubidaSP.log
    }

     


    Un saludo

    Fernando Reyes [MS MVP]
    MCSA 2000/2003
    MCSE 2000/2003
    MCITP EnterpriseAdministrator
    Web: http://freyes.svetlian.com
    Blog: http://urpiano.wordpress.com
    RSS: http://urpiano.wordpress.com/feed/
    freyes.champú@champú.mvps.org
    (Aclárate la cabeza si quieres escribirme)
    viernes, 25 de febrero de 2011 8:12
    Moderador