UncleFather » 21 мар 2014 07:48, Пт
Задача:
На компьютере есть общие сетевые ресурсы. В определенное время с файлами, к которым дан общий доступ, производятся какие-либо запланированные задания, требующие монопольного доступа. Поэтому, перед началом выполнения задания необходимо закрывать все открытые пользователями по сети файлы.
Примечание: из графического интерфейса открытые файлы можно посмотреть из оснастки «Управление компьютером» -> Общие папки -> Открытые файлы.
Решение:
Существует рекомендация от 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}
}
}
[b][size=150]Задача:[/size][/b]
На компьютере есть общие сетевые ресурсы. В определенное время с файлами, к которым дан общий доступ, производятся какие-либо запланированные задания, требующие монопольного доступа. Поэтому, перед началом выполнения задания необходимо закрывать все открытые пользователями по сети файлы.
[b]Примечание:[/b] из графического интерфейса открытые файлы можно посмотреть из оснастки [b][i]«Управление компьютером» -> Общие папки -> Открытые файлы[/i][/b].
[b][size=150]Решение:[/size][/b]
Существует рекомендация от Microsoft: [url=http://support.microsoft.com/kb/q290585]«Как закрыть с помощью командной строки все файлы, открытые сетевыми клиентами»[/url]
Собственно, на ее базе можно отбирать любые варианты файлов. Например, по расширению, по части пути и пр.
Следующий пример из командной строки закрывает все открытые файлы с расширением «[b][i].CDX[/i][/b]»:
[code]for /f "skip=4 tokens=1,2" %a in ('net files') do if %~xb==.CDX net files %a /close[/code]
Конечно, использование PowerShell, будет гораздо удобнее. Если в ранних версиях (до 2 включительно) для получения списка открытых файлов мы могли использовать тот же «net files», то в более старших версиях появился командлет «Get-SmbOpenFile».
Для свежих версий PowerShell все просто. Приведу пример, закрывающий открытые по сети файлы с расширением «[b][i].xls[/i][/b]»
[code]Get-SmbOpenFile | foreach-object {if ($_.path -like "*.xls") {Close-SmbOpenFile -Force -FileId $_.FileID}}[/code]
Для ранних версий PowerShell скрипт не намного сложнее. Сначала получаем список открытых файлов «net files», потом выбираем из них те которые нужно закрыть, и потом уже закрываем их «net files /close».
В приведенном примере закрываются все файлы из папки «[b][i]c:\Soft[/i][/b]»:
[code](net files | select-string -pattern 'c:\\Soft\\' -allmatches) -split "\s",2 | select-string -Pattern "c:\\Soft\\" -NotMatch | foreach-object {net files $_ /close}[/code]
Кроме «net files», для старых версий, для удобства можно использовать следующую [url=https://kazunposh.wordpress.com/2011/05/13/%D0%B2%D1%8B%D0%B2%D0%BE%D0%B4-%D0%B8%D0%BC%D0%B5%D0%BD-%D0%BE%D1%82%D0%BA%D1%80%D1%8B%D1%82%D1%8B%D1%85-%D0%BE%D0%B1%D1%89%D0%B8%D1%85-%D1%84%D0%B0%D0%B9%D0%BB%D0%BE%D0%B2-%D0%BD%D0%B0-%D1%81%D0%B5/]функцию[/url], позволяющую как выводить список открытых файлов, так и закрывать их:[spoiler title=Вывод имен открытых общих файлов][code]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}
}
}[/code][/spoiler]