Cómo administrar identificadores de archivos abiertos con PowerShell

Julia Tim / Shutterstock

Uno de los errores más frustrantes que puede enfrentar un usuario final o administrador de TI es el de los archivos bloqueados dentro de Windows. Cuando elimina una carpeta, mueve un archivo o cambia una configuración y encuentra un mensaje de error relacionado con el archivo bloqueado, es mejor manejarlo de manera rápida y eficiente.

Microsoft introdujo PowerShell como un shell de reemplazo, pero tiene mucha más funcionalidad que eso y es un lenguaje complejo y capaz. Echemos un vistazo en este artículo sobre cómo usar PowerShell para administrar archivos bloqueados.

→ Índice de contenidos

El problema del archivo bloqueado

¿Cómo se bloquea exactamente un archivo? Durante el uso normal, un proceso crea muchos identificadores de recursos como un archivo. De esta manera, los procesos a menudo bloquean el archivo para evitar cambios de configuración involuntarios u otros daños. El problema a menudo es que es difícil determinar qué proceso bloqueó el archivo y, posteriormente, cómo eliminar ese bloqueo del archivo.

Desafortunadamente, no hay un cmdlet integrado para probar un archivo y determinar si está bloqueado o por qué proceso. Por lo tanto, debe crear sus propias funciones o incluir otras herramientas útiles existentes que lo ayuden a obtener más información sobre estos archivos.

Buscar archivos bloqueados

En Windows, puede verificar si un solo archivo está bloqueado. Con el siguiente bloque de código, puede verificar si un archivo en particular está bloqueado. La $Item La variable debe establecerse en una ruta de archivo completamente calificada. Prueba para ver si el archivo se puede abrir para escritura, como se ve con el [System.IO.File]::Open($Item,'Open','Write') comando, puede saber si el archivo está bloqueado.

If ([System.IO.File]::Exists($Item)) {
  Try {
      $FileStream = [System.IO.File]::Open($Item,'Open','Write')

      $FileStream.Close()
      $FileStream.Dispose()

      $IsLocked = $False
  } Catch [System.UnauthorizedAccessException] {
      $IsLocked = 'AccessDenied'
  } Catch {
      $IsLocked = $True
  }
}

Get-SMBOpenFile

Dije que Windows no tiene una función incorporada, pero hay un caso en el que hay una función. Si tiene un recurso compartido remoto o incluso un recurso compartido administrativo (como c$), entonces puede usar el archivo Get-SMBOpenFile cmdlet para informar sobre esos archivos abiertos.

PS C:> Get-SMBOpenFile

FileId       SessionId    Path  ShareRelativePath
------       ---------    ----  -----------------
154618822665 154618822657 C:

PS C:> 

La desventaja es que solo funciona para archivos a los que se accede de forma remota. No se informará de ningún archivo bloqueado en uso en el sistema local, por lo que en la mayoría de los casos esta no es una solución viable. Para cerrar, puede redirigir los archivos abiertos devueltos al archivo Close-SMBOpenFile mando.

Get-SMBOpenFile | Close-SMBOpenFile

Utilidad OpenFiles

Windows tiene una utilidad incorporada llamada openfiles que puede ayudarlo a enumerar qué archivos están en uso y desconectarlos. ¡A primera vista se ve perfecto para tus necesidades! Incluso puede envolverlo en una función de PowerShell para facilitar la consulta y desconexión de archivos.

Abra un indicador de PowerShell administrativo y ejecute el comando openfiles /query. Inmediatamente, debería recibir un mensaje de error que indica que la marca global "mantener lista de objetos" debe estar activada.

PS C:/> openfiles /query

INFO: The system global flag 'maintain objects list' needs
      to be enabled to see local opened files.
      See Openfiles /? for more information.


Files opened remotely via local share points:
---------------------------------------------

INFO: No shared open files found.

Esta lista de objetos es lo que realmente mantiene la lista de identificadores en uso y habilitada openfiles para consultar esta información. Para activarlo, ingrese openfiles /local on y luego reinicie su computadora. La desventaja de habilitar esta función es que hay una ligera caída en el rendimiento, que dependiendo de su sistema puede que no valga la pena el uso de esta herramienta. Dicho esto, veamos cómo podemos hacer que funcione dentro de PowerShell.

PS C:> openfiles /Query /fo csv /nh

Files opened remotely via local share points:
---------------------------------------------
"ID","Accessed By","Type","Open File (Pathexecutable)"
"608","user","Windows","C:"

PS C:> openfiles /Query /fo csv | Select-Object -Skip 4 | ConvertFrom-CSV

ID  Accessed By  Type    Open File (Pathexecutable)
--  -----------  ----    ---------------------------
608 user         Windows C:

PS C:> openfiles /disconnect /id 608

SUCCESS: The connection to the open file "C:" has been terminated.

Con los ejemplos anteriores, puede ver cómo importar la salida CSV de openfiles en PowerShell. Con esta información, puede hacerlo disconnect un archivo para desbloquearlo. Debido a la degradación del rendimiento, puede experimentar la activación de maintain objects list capacidad, puede que no sea útil para sus necesidades. Por esta razón, es posible que se necesiten otras soluciones.

La aplicación del mango.

Sysinternals es conocido por las muchas herramientas de TI útiles y casi esenciales que produce. Hace un tiempo, Microsoft adquirió Sysinternals y usted puede descargar y usar estas herramientas bien soportadas por usted mismo. Convenientemente, hay una aplicación llamada handles que proporciona exactamente lo que está buscando.

Primero, debes hacerlo Descargar aplicación, descomprima los archivos y coloque los ejecutables en una ubicación incluida en la variable de entorno Path. De esta manera, puede consultar fácilmente la aplicación donde la necesite. Con una consulta simple para archivos abiertos, puede ver que obtiene muchos resultados (truncados para facilitar la lectura).

PS C:/> handle64 -NoBanner
...
------------------------------------------------------------------------------
RuntimeBroker.exe pid: 9860 User
   48: File          C:WindowsSystem32
  188: Section       BaseNamedObjects__ComCatalogCache__
  1EC: Section       BaseNamedObjects__ComCatalogCache__
------------------------------------------------------------------------------
chrome.exe pid: 4628 User
   78: File          C:Program Files (x86)GoogleChromeApplication78.0.3904.108
  1C4: Section       Sessions1BaseNamedObjectswindows_shell_global_counters
...

Parece que obtiene lo que desea, al menos una forma de averiguar qué archivos se están utilizando, y puede probarlos usando su código de archivo bloqueado de antes. Pero, ¿cómo puedes hacer que sea más fácil de usar? El siguiente código lee cada proceso y recupera solo los archivos bloqueados. La desventaja es que esto lleva algo de tiempo ya que hay muchos procesos.

$Processes = Get-Process

$results = $Processes | Foreach-Object {
    $handles = (handle64 -p $_.ID -NoBanner) | Where-Object { $_ -Match " File " } | Foreach-Object {
            [PSCustomObject]@{
        "Hex"  = ((($_ -Split " ").Where({ $_ -NE "" })[0]).Split(":")[0]).Trim()
        "File" = (($_ -Split " ")[-1]).Trim()
        }
    }

    If ( $handles ) {
        [PSCustomObject]@{
            "Name"    = $_.Name
            "PID"     = $_.ID
            "Handles" = $handles
        }
    }
}

Sin embargo, en última instancia, lo que obtiene es una colección de archivos utilizables, enumerados por proceso, que sabe que están en uso y que se pueden filtrar más. Si encuentra que necesita cerrar uno, puede hacer lo siguiente (como administrador):

PS C:> $results |
>>  Where-Object Name -EQ 'Notepad' |
>>  Where-Object { $_.Handles.File -Match "test.txt" }

Name                      PID Handles
----                      --- -------
Notepad                   12028 {@{Hex=44; File=C:test.txt}


PS C:> handle64 -p 12028 -c 44 -y -nobanner

44: File  (R-D)   C:test.txt

Handle closed.

Puede empaquetar todo esto en una sola función para facilitar aún más el análisis y la búsqueda si es necesario. Hay muchas posibilidades, especialmente al combinar los distintos métodos en una solución adecuada para su entorno.

Conclusión

Tratar con archivos bloqueados puede ser un desafío, especialmente cuando interrumpe lo que debe hacerse rápidamente. Hay varias formas de encontrar y desbloquear esos archivos, pero requiere algo de trabajo ya que Windows no tiene un método integrado realmente completo para tratar esos archivos bloqueados. Las soluciones descritas deberían simplificar el trabajo de cualquiera que sea el problema y permitirle pasar a tareas mucho más importantes.

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

Subir Change privacy settings