Я работаю с большим количеством долей папки, но существует набор заблокированных файлов, которые были открыты некоторым другим процессом.
Я должен закрыть те файлы. До сих пор я использовал MMC - Системные Инструменты - Совместно используемые папки - Открывают Files.
Было бы намного более удобно, если я мог бы использовать PowerShell для фильтрации списка/таблицы, полученного OpenFiles.exe и после того как я добираюсь, идентификатор файла закрывают его с сетевым файлом / близко, или некоторый другой собственный компонент PS значит для подобного эффекта.
Я плохо знаком с PowerShell, поэтому интересно, существует ли способ создать сценарий PS, который получает путь файла и затем использовал идентификатор файла для закрытия того файла?
Есть ли причина, по которой вам нужно использовать и openfiles.exe
, и сетевой файл
?
Ниже представлена функция, которая использует только сетевой файл
и оборачивает его вокруг сценария PowerShell.
Чтобы использовать его, вы можете скопировать весь код и вставить его в сеанс PowerShell. В качестве примечания: вам необходимы права администратора для использования сетевого файла
и открытых файлов
.
После того, как вы вставите его в свой сеанс, вы сможете использовать функцию Close-OpenFile
. Использование очень простое. Вы можете передать пути к файлам в функцию или указать пути к файлам в качестве параметра.
Если вы вставили его как есть,вы можете получить справку, используя Get-Help Close-OpenFile -Example
, чтобы увидеть примеры. Ниже приведены те же примеры для вашего удобства.
# Method 1 : Pipeline
@("file\path\1", "file\path\2") | Close-OpenFile
"file\path\1" | Close-OpenFile
# Method 2 : Parameter
Close-OpenFile @("file\path\1", "file\path\2")
Close-OpenFile "file\path\2"
Теперь предположим, что вы хотите использовать это каждый раз, когда открываете PowerShell. Я предоставил основной способ сделать это (есть и другие способы сделать это) в конце этого ответа.
<#
.Synopsis
Closes Files Opened in Network Share
.EXAMPLE
@("file\path\1", "file\path\2") | Close-OpenFile
Attempts to close "file\path\1" and "file\path\2" if they are open.
.EXAMPLE
Close-OpenFile @("file\path\1", "file\path\2")
Attempts to close "file\path\1" and "file\path\2" if they are open.
.EXAMPLE
"file\path\1" | Close-OpenFile
Attempts to close "file\path\1" if it is open.
.EXAMPLE
Close-OpenFile "file\path\2"
Attempts to close "file\path\2" if it is open.
#>
function Close-OpenFile {
[CmdletBinding()]
Param (
[Parameter(Mandatory=$true,
ValueFromPipeline = $true,
ValueFromPipelineByPropertyName=$true,
Position=0)]
[String[]]$filesToClose
)
Begin {
$netFile = net file
if($netFile.length -lt 7) { Throw "No Files are Open" }
$netFile = $netFile[4..($netFile.length-3)]
$netFile = $netFile | ForEach-Object {
$column = $_ -split "\s+", 4
New-Object -Type PSObject -Property @{
ID = $column[0]
FilePath = $column[1]
UserName = $column[2]
Locks = $column[3]
}
}
$count = 0
} Process {
ForEach ($file in $filesToClose) {
ForEach ($openFile in $netFile) {
if($openFile.FilePath -eq $file) {
$count++
net file $openfile.ID /close > $null
}
}
}
} End { Write-Output "Closed $count Files" }
}
Ниже показан базовый способ использования этой функции каждый раз, когда вы открываете PowerShell.
$ env: homepath \ Documents \ WindowsPowerShell
(создайте его, если у вас его нет). C: \ Users \ \ Documents \ WindowsPowerShell
. profile.ps1
(или Microsoft.PowerShell_profile.ps1
). Close-OpenFiles
и сохраните ее. Вот быстрое и грязное использование CMD и OpenFiles.exe. Я уверен, что при необходимости это можно было бы быстро перевести на PoSH. Сохраните его как CloseFile.cmd и поместите в папку на своем пути.
@echo off
if "%1" == "" goto SYNTAX
if "%2" == "" goto SYNTAX
goto RUNIT
:SYNTAX
echo Use:
echo CloseFile.cmd ^<server^> ^<file^>
goto :EOF
:RUNIT
set _server=%1
set _file=%2
openfiles /query /s %_server% /fo csv | findstr /i /c:"%_file%" > _filelist.txt
for /f "tokens=1,4 delims=," %%a in (_filelist.txt) do (
openfiles /disconnect /s %_server% /op %%b /id %%a
)
if exist _filelist.txt del _filelist.txt
Get-SmbOpenFile и Close-SmbOpenFile выполнят эту работу за вас.
Войдите в свой файловый сервер, запустите PowerShell. Используйте Get-SmbOpenFile, чтобы отобразить все открытые файлы на вашем файловом сервере. Файлы будут отображаться вместе со следующими заголовками таблиц
FileId SessionId Path ShareRelativePath ClientComputerName ClientUserName
Используйте Close-SmbOpenFile, чтобы закрыть файл.
Close-SmbOpenFile -FileId 4415226383589
Если вы знаете, что проблема в файле Excel, вы можете сузить поиск для всех открытых файлов с расширением .XLSX.
Get-SmbOpenFile | Where-Object -Property sharerelativepath -match ".XLSX"
Найдя в результатах проблемный файл, вы можете закрыть его по идентификатору файла.
Если вы хотите закрыть все открытые файлы на файловом сервере:
Get-SmbOpenFile | Close-SmbOpenFile
Если вы хотите закрыть один или несколько открытых файлов с расширением ".XLSX".
Get-SmbOpenFile | Where-Object -Property sharerelativepath -match ".XLSX" | Close-SmbOpenFile -Force
**** ПРИМЕЧАНИЕ **** Согласно статье TechNet «Командлет Close-SMBOpenFile принудительно закрывает файл, открытый одним из клиентов сервера Server Message Block (SMB). ] Этот командлет следует использовать с осторожностью, поскольку он может привести к потере данных для клиента , для которого файл закрывается, если клиент не сбросил все изменения файла обратно на сервер до закрытия файла ».
Дополнительные сведения о CMDlets
Get-SmbOpenFile https://technet.microsoft.com/en-us/library/jj635701 (v = wps.620) .aspx
Close-SmbOpenFile https://technet.microsoft.com/en-us/library/jj635721 (v = wps.620) .aspx