Como gerenciar identificadores de arquivo aberto com PowerShell

Conteúdo

Pessoas da linha de comando

Um dos erros mais frustrantes com que um usuário final ou administrador de TI pode lidar é o bloqueio de arquivos no Windows.. Quando você apaga uma pasta, você move um arquivo ou edita uma configuração e encontra uma mensagem de erro de arquivo bloqueado, melhor lidar com isso de forma rápida e eficiente.

A Microsoft apresentou o PowerShell como um shell substituto, mas tem muito mais funcionalidade do que isso e é uma linguagem complexa e capaz. Vamos ver neste post como você pode usar o PowerShell para lidar com arquivos bloqueados.

O problema do arquivo bloqueado

Como exatamente você bloqueia um arquivo? Durante o uso normal, um procedimento cria muitos identificadores de recursos como um arquivo. Ao fazer isso, processos muitas vezes bloqueiam o arquivo para evitar alterações de configuração indesejadas ou outro tipo de corrupção. O problema geralmente é que é difícil determinar qual procedimento bloqueou o arquivo e, subseqüentemente, como limpar aquele bloqueio de arquivo.

Infelizmente, não há cmdlet embutido para testar um arquivo e descobrir se ele está bloqueado ou por qual procedimento. Por isso, você precisa criar suas próprias funções ou empacotar outras ferramentas úteis para ajudá-lo a aprender mais sobre esses arquivos.

Teste de arquivos bloqueados

Dentro de Windows, você pode testar para ver se um arquivo individual está bloqueado. Com o seguinte bloco de código, você pode testar para ver se um determinado arquivo está bloqueado. a $Item A variável deve ser definida para um caminho de arquivo completo. Ao testar para ver se o arquivo pode ser aberto para gravação, como fica com ele [System.IO.File]::Open($Item,'Open','Write') comando, você pode dizer se o arquivo 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

Eu disse que o Windows não tem uma função integrada, mas há um caso em que existe uma função. Se você tiver um compartilhamento remoto ou mesmo administrativo (O que c$), então você pode usar o Get-SMBOpenFile cmdlet para relatar sobre os arquivos abertos.

PS C:> Get-SMBOpenFile

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

PS C:> 

A desvantagem é que isso só funciona para arquivos que são acessados ​​remotamente. Nenhum arquivo bloqueado em uso em seu sistema local será relatado, então, na maioria dos casos, esta não é uma solução viável. Para fechar, você pode canalizar arquivos abertos retornados ao Close-SMBOpenFile comando.

Get-SMBOpenFile | Close-SMBOpenFile

Utilitário OpenFiles

O Windows tem um utilitário integrado chamado openfiles o que pode ajudar a listar quais arquivos estão em uso e desconectá-los. A primeira vista, parece perfeito para suas necessidades! Você pode até envolver isso dentro de uma função do PowerShell para tornar mais fácil verificar e desconectar arquivos..

Abra um prompt administrativo do PowerShell e execute o comando openfiles /query. De imediato, você deve receber uma mensagem de erro que indica que a bandeira global “manter lista de objetos” deve ser habilitado.

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 é o que realmente mantém a lista de identificadores que estão em uso e permite openfiles consultar essa informação. Para ativar este, entra openfiles /local on e reinicie o seu computador. A desvantagem de ativar esse recurso é que há um pequeno impacto no desempenho, que dependendo do seu sistema, esta ferramenta pode não valer a pena usar. Tendo dito isto, vamos ver como podemos fazer isso funcionar dentro do 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.

Com os exemplos acima, você pode ver como importar a saída CSV de openfiles e PowerShell. Com essa informação, poderia disconnect um arquivo para desbloquear. Devido ao impacto no desempenho que você pode incorrer ao ativar o maintain objects list capacidade, pode não valer a pena para suas necessidades. É por isto que, outras soluções podem ser necessárias.

A aplicação da alça

A Sysinternals é conhecida pelas muitas ferramentas de TI úteis e quase essenciais que fabrica. Faz tempo, A Microsoft adquiriu a Sysinternals e você pode baixar e usar essas ferramentas bem suportadas por conta própria. Convenientemente, existe um aplicativo chamado handles que fornece exatamente o que você está procurando.

Primeiro, você deve descargar a aplicação, descompacte os arquivos e coloque os executáveis ​​em um local que inclua sua variável de ambiente Path. Ao fazer isso, você pode consultar facilmente o aplicativo onde precisar. Com uma consulta simples para arquivos abertos, você pode ver que consegue muitos resultados (truncado para facilitar a leitura).

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
...

Você parece conseguir o que quer, pelo menos uma maneira de descobrir quais arquivos estão sendo usados, e você pode testá-los usando o código de arquivo bloqueado de antes. Mas, Como você torna isso mais fácil de usar? O código a seguir lê cada procedimento e recupera apenas os arquivos bloqueados. A desvantagem é que demora um pouco para ser executado, pois há muitos processos.

$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
        }
    }
}

Apesar disto, em última instância, o que você obtém é uma coleção de arquivos acionável, listado por procedimento, que você sabe que estão em uso e podem ser filtrados posteriormente. Se você achar que precisa fechar um deles, você pode fazer o seguinte (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.

Você pode agrupar tudo isso em uma função para tornar ainda mais fácil analisar e pesquisar conforme necessário.. Existem muitas alternativas, especialmente na combinação de vários métodos em uma solução que se adapta ao seu ambiente.

conclusão

Lidar com arquivos bloqueados pode ser um desafio, especialmente quando você interrompe o que precisa fazer rapidamente. Existem várias alternativas para encontrar e desbloquear esses arquivos, mas dá um pouco de trabalho, pois o Windows não tem um método integrado verdadeiramente abrangente para lidar com esses arquivos bloqueados. As soluções descritas devem manter o problema breve e permitir que você prossiga para tarefas muito mais importantes.

Assine a nossa newsletter

Nós não enviaremos SPAM para você. Nós odiamos isso tanto quanto você.