Как из командной строки закрыть открытые по сети файлы

Все об администрировании рабочих станций Windows 95/98/NT/2000/XP/7/8. То, чего не найдешь в бескрайних просторах Интернета. Решения тех проблем, которые не решаются типовыми ответами, которые можно получить в техподдержке Майкрософта - а именно: переустановить продукт или купить какой-ть другой лицензионный диск.


Модератор: UncleFather

Аватара пользователя
UncleFather
Site Admin
Сообщения: 1505
Зарегистрирован: 17 авг 2004 16:20, Вт
Контактная информация:

Как из командной строки закрыть открытые по сети файлы

Сообщение UncleFather »

Задача:

На компьютере есть общие сетевые ресурсы. В определенное время с файлами, к которым дан общий доступ, производятся какие-либо запланированные задания, требующие монопольного доступа. Поэтому, перед началом выполнения задания необходимо закрывать все открытые пользователями по сети файлы.

Примечание: из графического интерфейса открытые файлы можно посмотреть из оснастки «Управление компьютером» -> Общие папки -> Открытые файлы.

Решение:

Существует рекомендация от Microsoft: «Как закрыть с помощью командной строки все файлы, открытые сетевыми клиентами»

Собственно, на ее базе можно отбирать любые варианты файлов. Например, по расширению, по части пути и пр.

Следующий пример из командной строки закрывает все открытые файлы с расширением «.CDX»:

Код: Выделить всё

for /f "skip=4 tokens=1,2" %a in ('net files') do if %~xb==.CDX net files %a /close

Конечно, использование PowerShell, будет гораздо удобнее. Если в ранних версиях (до 2 включительно) для получения списка открытых файлов мы могли использовать тот же «net files», то в более старших версиях появился командлет «Get-SmbOpenFile».

Для свежих версий PowerShell все просто. Приведу пример, закрывающий открытые по сети файлы с расширением «.xls»

Код: Выделить всё

Get-SmbOpenFile | foreach-object {if ($_.path -like "*.xls") {Close-SmbOpenFile -Force -FileId $_.FileID}}

Для ранних версий PowerShell скрипт не намного сложнее. Сначала получаем список открытых файлов «net files», потом выбираем из них те которые нужно закрыть, и потом уже закрываем их «net files /close».
В приведенном примере закрываются все файлы из папки «c:\Soft»:

Код: Выделить всё

(net files | select-string -pattern 'c:\\Soft\\' -allmatches) -split "\s",2 | select-string -Pattern "c:\\Soft\\" -NotMatch | foreach-object {net files $_ /close}

Кроме «net files», для старых версий, для удобства можно использовать следующую функцию, позволяющую как выводить список открытых файлов, так и закрывать их:

Вывод имен открытых общих файлов

Код: Выделить всё

Function Get-OpenFiles
{
    <#
        Аналог утилиты net file.Запуск скрипта без параметров,выведет список открытых общих файлов,
        так же поддерживается функция закрытия файлов,как на локальном,там и на удаленном ПК.
 
        Требуются права администратора или соответсвующие. Сервис Server должен быть запущен.
 
        Пример:
 
        PS >  Get-OpenFiles
        PS >  Get-OpenFiles -Id 510
        PS >  "Server1","Server2" | Get-OpenFiles
    #>
 
    [CmdletBinding()]
    param (
             [parameter(Position=0,ValueFromPipeline=$true,ValueFromPipelineByPropertyName=$true)]
             [alias("CN")]
             [String[]]$ComputerName = ".",
             [parameter(ParameterSetName="Close")]
             [int[]]$Id
          )
 
    begin {
            #Объявляем функцию NetFileClose
            $signature = @"
            [DllImport("netapi32.dll", SetLastError=true, CharSet = CharSet.Unicode)]
            public static extern int NetFileClose(
                string servername,
                int id);
"@
            $type = Add-Type -MemberDefinition $signature -Name NetFile -Namespace Win32.Function -PassThru
          }
 
    process {
            #Получаем список открытых файлов
            foreach ($server in $ComputerName)
            {
                $netfile = [ADSI]"WinNT://$server/LanmanServer"
                #Получаем свойства интерфейса IADsResource
                $netfile.Invoke("Resources") | foreach {$collection = @()} {
                    $collection += New-Object PsObject -Property @{
                            Id = $_.GetType().InvokeMember("Name", 'GetProperty', $null, $_, $null)
                            Path = $_.GetType().InvokeMember("Path", 'GetProperty', $null, $_, $null)
                            UserName = $_.GetType().InvokeMember("User", 'GetProperty', $null, $_, $null)
                            LockCount = $_.GetType().InvokeMember("LockCount", 'GetProperty', $null, $_, $null)
                            Server = $server
                        }
                }
            }
        }
 
    end {
            #Если задан параметр -Id ,пытаемся закрыть доступ к файлу
            if ($pscmdlet.ParameterSetName -eq "Close"){
                foreach ($i in $Id)
                {
                    $collection | Where-Object {$_.Id -eq $i} | Foreach {
                                $type::NetFileClose($_.Server,$_.Id)
                    }
                }
            }
            #Если параметр -Id не задан,выводим список открытых файлов.
            else {$collection}
        }
}

Alexander A. Manaeff©

Понравилась статья? Будем крайне признательны за репосты в соцсетях! Материально поддержать проект можно здесь

Мои странички:
ВКонтакте
Одноклассники
Youtube
Facebook
Instagram

Изображение
Изображение
Изображение
Изображение