Компьютерный форум OSzone.net  

Компьютерный форум OSzone.net (http://forum.oszone.net/index.php)
-   Скриптовые языки администрирования Windows (http://forum.oszone.net/forumdisplay.php?f=102)
-   -   Открытие файлов по расширению не работает (http://forum.oszone.net/showthread.php?t=345607)

ilayka 21-06-2020 20:04 2925828

Открытие файлов по расширению не работает
 
Не работает в винде 10 найденный в теме батник http://forum.oszone.net/thread-249124.html
Задача такая: есть расшаренная папка С:\PDF\ в нее по локалке копируются файлы с разными именами и разными расширениями...необходимо отслеживать файлы pdf в этой папке и при обнаружении открывать их соответственно акробатом. Причем открывать все новые файлы pdf, даже если предыдущие не закрыты. Открытие по имени файла я сделал, не сложно, а вот по расширению не получается. Ткните куда копать.

Iska 21-06-2020 23:07 2925847

ilayka, где расположен:
Цитата:

Цитата ilayka
соответственно акробатом »

? Какого размера файлы? Как часто нужно проверять?

Fors1k 22-06-2020 12:58 2925876

Powershell
Код:

Param(
    $path  = "С:\PDF",  # Путь к папке
    $delay = 3          # Проверять каждые 3 секунды
)cls

while($true){
    (gci $path *.pdf)|foreach{if($_.LastAccessTime -gt $d)
    {&($a=$_.FullName)}};sleep $delay;if($a){$d=date;rv a}
}


ilayka 22-06-2020 22:26 2925942

Цитата:

Цитата Iska
Какого размера файлы? Как часто нужно проверять? »

Размер разный, проверять каждые 2 секунды. Расположение я написал выше...С:\PDF\

YuS_2 23-06-2020 12:29 2925984

powershell
Код:

$prog = "C:\Program Files (x86)\Adobe\Acrobat Reader DC\Reader\AcroRd32.exe"
$pth = "d:\111"
$wtch = new-object system.io.filesystemwatcher
$wtch.path = $pth
$wtch.filter = "*.pdf"
while ($true) {
        sleep -m 500
        $res = $wtch.waitforchanged("created")
        write-host "открываем файл $($res.name)" -for cyan
        &$prog $($pth+'\'+$res.name)
}


Busla 23-06-2020 12:56 2925988

YuS_2, sleep не нужен

YuS_2 23-06-2020 15:03 2926000

Цитата:

Цитата Busla
sleep не нужен »

писалось давно, уже точно не помню зачем впихнул sleep... что-то там в цикле подвисало, если не будет паузы короткой, вроде бы так. А так да, в принципе, не нужен он...

Fors1k 23-06-2020 16:50 2926015

Цитата:

Цитата Busla
sleep не нужен »

Sleep здесь нужен.

В waitforchanged следует передавать два параметра.
Открывать файлы нужно не из ответа watcher.

Код:

Param(
    $path  = "С:\PDF"
)cls

$watcher = new-object io.filesystemwatcher
$watcher.path = $path
$watcher.filter = "*.pdf"

while($true){
    $d=date
    while(!($watcher.waitforchanged("created",1).Name)){}
    sleep 2
    gci $path *.pdf|? LastAccessTime -gt $d|%{&$_.FullName}
}


YuS_2 23-06-2020 17:17 2926019

Цитата:

Цитата Fors1k
В waitforchanged следует передавать два параметра. »

хмм, совсем необязательно... waitforchanged

Цитата:

Цитата Fors1k
while(!($watcher.waitforchanged("created",1).Name)){} »

а это для чего?

Цитата:

Цитата Fors1k
gci $path *.pdf|? LastAccessTime -gt $d|%{&$_.FullName} »

- это лишнее. Каталог сканировать и фильтровать файлы по условию сравнения дат, тоже не требуется. Watcher сам всё сделает как надо.
При появлении нового файла, он будет отслежен по указанному событию и результатом, уже будет объект, в котором содержится имя файла, его просто надо будет открыть. По условию задачи, этого достаточно.

Fors1k 23-06-2020 17:36 2926024

Цитата:

Цитата YuS_2
хмм, совсем необязательно »

Необязательно, только тогда его остановить будет невозможно))
Цитата:

Цитата YuS_2
а это для чего? »

Это ожидание появления нового файла в папке.
Цитата:

Цитата YuS_2
Watcher сам всё сделает как надо. »

За watcher спасибо, но сделать все он не сможет. Сольно watcher подойдет для отслеживания либо одного файла, либо папки но на предмет факта изменений в ней. А нам нужно не только знать что в папке что-то произошло, но и узнать какие именно файлы были скопированы. Так, к примеру, если в папку скопировать 2 (или больше) файла, то watcher сообщит нам только об одном, а второй проскочит мимо нас.

YuS_2 23-06-2020 21:26 2926058

Цитата:

Цитата Fors1k
Необязательно, только тогда его остановить будет невозможно)) »

а зачем его останавливать? Ну, даже если надо, то закрываем сессию и всё выключается...

Цитата:

Цитата Fors1k
Это ожидание появления нового файла в папке. »

Не совсем. Цикл там зачем?
Для ожидания, достаточно:
Код:

$watcher.waitforchanged("created")
и пока файл не появится, будет действовать ожидание...
или так:
Код:

$watcher.waitforchanged("created",-1)
а с таймаутом в 1 сек., ожидание, по факту, будет работать 1 сек. и продолжится цикл...

Цитата:

Цитата Fors1k
но сделать все он не сможет. »

В таком виде, да. Нужна подписка на события, тогда будет всё работать как надо и тогда этого:
Цитата:

Цитата Fors1k
если в папку скопировать 2 (или больше) файла, то watcher сообщит нам только об одном, а второй проскочит мимо нас. »

уже не произойдет.
Примерно так:
Код:

$wtch = new-object system.io.filesystemwatcher
$wtch.path  = "d:\111"
$wtch.filter = "*.pdf"
register-objectevent -inp $wtch -event Created -action {
        $prog = "C:\Program Files (x86)\Adobe\Acrobat Reader DC\Reader\AcroRd32.exe"
        $obj = "{0} создан {1}" -f $event.sourceeventargs.fullpath,$event.timegenerated
        $params  = @{Object = $obj;ForegroundColor = 'cyan'}
        write-host @params
        &$prog $event.sourceeventargs.fullpath
}


Fors1k 23-06-2020 23:13 2926078

Цитата:

Цитата YuS_2
а зачем его останавливать? »

Например, что бы поправить что-то в коде. Что мне делать с этой красотой? :)
Цитата:

Цитата YuS_2
Цикл там зачем?
Для ожидания, достаточно: »

Цикл нужен, если вызываем с таймаутом, который дает возможность нажать стоп.
Цитата:

Цитата YuS_2
Нужна подписка на события, тогда будет всё работать как надо »

Вот такой вариант - да, вопрос решает полностью :good:

YuS_2 24-06-2020 08:05 2926098

Цитата:

Цитата Fors1k
Например, что бы поправить что-то в коде. »

Цитата:

Цитата YuS_2
Ну, даже если надо, то закрываем сессию и всё выключается... »

Как вариант... ибо при автоматизации слежения, паузы увеличивают вероятность пропуска фалов, либо получения ложных дубликатов...
В общем, не совсем корректная работа кода получается... с лишним сканированием каталога и доп. проверками.

Цитата:

Цитата Fors1k
Цикл нужен, если вызываем с таймаутом, который дает возможность нажать стоп. »

Рабочий код не будет ведь запускаться через ISE, там нет никакого "стоп"...
В крайнем случае, можно использовать общий цикл do {} until ([console]::keyavailable) - как-то так. Но, в любом случае, это такое же "ручное вмешательство в работу кода", в том смысле, что в данном случае, проще прервать сессию, чем предусматривать какую-либо ручную остановку...

ЗЫ
Кстати, ISE - устаревший уже IDE, сейчас есть более актуальные, например Visual Studio Code...
Цитата:

The PowerShell ISE is no longer in active feature development. As a shipping component of Windows, it continues to be officially supported for security and high-priority servicing fixes. We currently have no plans to remove the ISE from Windows.

There is no support for the ISE in PowerShell v6 and beyond. Users looking for replacement for the ISE should use Visual Studio Code with the PowerShell Extension.

ilayka 24-06-2020 21:34 2926166

Спасибо всем. Но это п-шелл...к нему нужно еще батник с разрешением прикручивать. Отслеживание и авто-откр нужно делать на удаленной машине. В принципе прикрутить не сложно...однако я думал есть возможность только средствами бат файла, планировщика или микропрогой sleep реализовать.

Fors1k 25-06-2020 16:02 2926250

YuS_2, раз уж пошла такая пьянка, давай замутим командлет ему))
Сделал вот такой набросок, пиши, если есть чего дополнить.
cmdlet
Код:

function Start-FileWatcher{
<#

.SYNOPSIS
        Запуск FileWatcher.

.DESCRIPTION
        Позволяет следить за изменениями в папке или файле.

.EXAMPLE
    (folder watch)
        $action = {$event.sourceeventargs.fullpath}
    Start-FileWatcher "PDF" "C:\Files" '*.pdf' 'Created' $action

.EXAMPLE
    (file watch)
        $action = {gc $event.sourceeventargs.fullpath}
    Start-FileWatcher "Test.txt" "C:\Files" "test.txt" 'Changed' $action

.PARAMETER name
        Имя наблюдателя

.PARAMETER path
        Путь к папке

.PARAMETER filter
        Фильтр наблюдения

.PARAMETER event
        Отслеживаемое событие:
            Created | Deleted | Renamed | Changed

.PARAMETER action
        Действия в случае изменения в папке/файле

.NOTES
        Author: Fors1k
#>
[Alias('swatch')][CmdletBinding()]
param(
    [parameter(Mandatory=$true)][string]      $name,
    [parameter(Mandatory=$true)][string]      $path,
    [parameter(Mandatory=$true)][string]      $filter,
    [parameter(Mandatory=$true)][string]      $event,
    [parameter(Mandatory=$true)][ScriptBlock] $action
)
    if(!$watchers){$global:watchers=@{}}
    $w=[io.filesystemwatcher]::new($path,$filter)
    if(!$watchers.ContainsKey($name)){
        $watchers.add($name,(register-objectevent $w $event -a $action -ea 1))
    }else{write-host "`n`t$name already exists`n" -fo Red}
    if($watchers.count -eq 0){rv watchers -Scope global -ea 0 -Force}
}


function Get-FileWatcher{[Alias('gwatch')][CmdletBinding()]param()
    if(!$watchers){
        write-host "`n`tNo watchers found`n" -fo Red
    }
    else{
            $watchers
    }
}


function Delete-FileWatcher{[Alias('dwatch')][CmdletBinding()]
param(
    [parameter(ValueFromPipelineByPropertyName=$true,
    ValueFromPipeline=$true,Mandatory=$true)]
    [string] $id
)
    if($id -eq 'all'){
        if(!$watchers){
            write-host "`n`tNo watchers found`n" -fo Red
        }
        else{ 
            $watchers.Values|rjb -force -ea 0
            rv watchers -Scope global -ea 0 -Force
            write-host "`n`tAll watchers are stopped`n" -fo Green
        }
    }
    else{
        if($id -in $watchers.Keys){
            $watchers.$id|rjb -force -ea 0
            $watchers.Remove($id)
            write-host "`n`tWatcher `"$id`" is stopped`n" -fo Green
        }
        else{
            write-host "`n`tWatcher `"$id`" is not found`n" -fo Red
        }

    }
}

Код:

$action={
    write-host $event.sourceeventargs.fullpath -fo DarkYellow
}
Swatch "PDF" "C:\files" '*.pdf' 'Created' $action

cls;sleep 2
123 > "C:\files\asd.pdf"

Код:

$action={
    write-host $event.sourceeventargs.fullpath -fo DarkYellow
}
Start-FileWatcher "Test.txt" "C:\files" "test.txt" 'Changed' $action

cls;sleep 2
2 >> "C:\files\test.txt"

Код:

Gwatch

'pdf'|Dwatch

Delete-FileWatcher all

Get-FileWatcher


YuS_2 25-06-2020 17:18 2926257

Fors1k, человек не хочет powershell, в принципе... сизифов труд, выполнять не хочется...
Ну, а если для себя, то в функцию старта, надо бы добавить проверки на правильные значения параметров и может быть, ещё и на наличие пути (если не указан, то текущий каталог) и т.п.
Сегодня, что-то думать нет особого желания... :)

Fors1k 25-06-2020 17:47 2926258

Цитата:

Цитата YuS_2
Ну, а если для себя »

Ага, для себя. Такая функция мне кажется весьма полезной)
Цитата:

Цитата YuS_2
Сегодня, что-то думать нет особого желания »

Так тут же срочности нет ни какой. Задача эта так... лишь пища для ума, как развлечение)

YuS_2 25-06-2020 20:52 2926285

Цитата:

Цитата Fors1k
пища для ума, как развлечение »

порылся тут на складе скриптов... попался готовый watchdog, слямзенный на киберфоруме, приведу полностью, как есть:
следящаясобака.ps1
Код:

<# Garry Geller http://www.cyberforum.ru/powershell/thread1561433.html#post10781770
mod by YuS (скорректирована реакция кода на появление двойных и более событий по одному и тому же файлу)
29.05.2019
Набор функций-командлетов для наблюдения за изменениями файлов\директорий на основе
класса FileSystemWatcher. Для удобства использования можно поместить их в файл
powershell профиля - тогда они будут доступны наравне с прочими командами сразу из
консоли, либо поместить файл модуля watchdog.ps1 в папку powershell модулей.
#>
# required -version 3.0

set-alias swatch Set-Watch
function Set-Watch() {
<#
        .SYNOPSIS
                Запускает фоновый процесс отслеживания изменений файловой системы на основе класса FileSystemWatcher
        .DESCRIPTION
                Существующие фильтры отслеживаемых изменений:
                NotifyFilters.CreationTime
                NotifyFilters.LastAccess
                NotifyFilters.LastWrite
                NotifyFilters.FileName
                NotifyFilters.DirectoryName
                NotifyFilters.Security
                NotifyFilters.Size
                NotifyFilters.Attributes
        .EXAMPLE
                PS C:\> . .\watchdog.ps1
                PS C:\> swatch -path "d:\test" -filter "*.txt"  -event Created,Deleted
        .EXAMPLE       
                PS C:\> swatch -path "d:\test" -filter "*.txt"  -event Created,Deleted  -command "start-process notepad.exe" -test
        .LINK
                https://msdn.microsoft.com/ru-ru/lib...v=vs.110).aspx
        .LINK
                Remove-Watch
        .LINK
                Disable-Watch
        .LINK
                Enable-Watch
        .LINK
                Get-Watch
#>

        [CmdletBinding()]
        param(
                # путь до отслеживаемой директории
                [parameter(Mandatory=$true,Position=1)]
                [alias("p")][string]$path,
                [parameter(Mandatory=$true,Position=2)]
                # фильтр типов отслеживаемых файлов
                [alias("f")][string]$filter="*.*",
                # задает тип отслеживаемых изменений
                [alias("n")][string]$notify='FileName, LastWrite',
                # нужно ли рекурсивно отслеживать субдиректории
                [alias("r")][switch]$recurse,
                # событи(e|я) на котор(ое|ые) нужно реагировать
                [parameter(Mandatory=$true,Position=3)]
                [ValidateSet("Created","Deleted","Renamed","Changed")]
                [alias("e")][string[]]$events,
                [parameter(Mandatory=$false)]
                # строковые идентифкаторы событий
                [alias("name")][string[]]$id=@(),
                # действие которое нужно выполнить - передается одной строкой вместе с аругментами
                [string]$command,
                # вывод переданных аргументов
                [switch]$test
        )

        $fsw = New-Object IO.FileSystemWatcher -Property @{
                Path = $path
                Filter = $filter
                IncludeSubdirectories = $recurse
                NotifyFilter = [IO.NotifyFilters]$notify
        }

        Set-Variable __watcher -Value $fsw -Scope Script
        Set-Variable command -Value $command -Scope Script
       
        $action = {
                $fullPath  = $event.SourceEventArgs.FullPath
                $fileName  = $event.SourceEventArgs.Name
                $changeType = $event.SourceEventArgs.ChangeType
                $timeStamp  = $event.TimeGenerated
                if (!$tmptime){$tmptime = $timeStamp}
                $dif = ((get-date($timeStamp)) - (get-date($tmptime))).totalseconds
                #write-host $dif -for red
                if ($dif -gt 1.0 -or $changeType -ne $tmpType -or $fileName -ne $tmpName){
                        #$command  = Get-Variable command -valueOnly -Scope Global
                        Write-Host $('The file "{1}" was {2} at {0:dd.MM.yyyy HH:mm:ss,ffff}' -f $timeStamp,$fileName,$changeType) -for green
                        if ($command) {
                                Invoke-Expression $command
                        }
                        $tmptime,$tmpType,$tmpName = $timeStamp,$changeType,$fileName
                }
        }

        $calls = [Collections.ArrayList]::new()

        for ($i=0; $i -lt $events.length; $i++) {
                if ($id.Length -eq $events.Length){
                        $jobname = $id[$i]
                } else {
                        $jobname = $events[$i]
                }

                $params = @{SourceIdentifier = $jobname; Action = $action}
                if ((get-job).Name -ccontains $jobname) {
                        Write-Host "Задание $jobname уже существует" -f Red
                } else {
                        $regEvent = Register-ObjectEvent $fsw $events[$i] @params
                        $calls.Add($regEvent)|Out-Null
                }
        }

        # выводим аргументы функции
        if ($test) {
                $MyInvocation.BoundParameters.GetEnumerator() | Foreach {
                        echo "-$($_.Key): $($_.Value)"
                }
                $MyInvocation.UnboundArguments
                '----------------------------'
        }
        return $calls
}

set-alias unwatch Disable-Watch
function Disable-Watch() {
<#
        .SYNOPSIS
                Временно отключает обработку событий
        .LINK
                Enable-Watch
        .LINK
                Remove-Watch
        .LINK
                Get-Watch
        .LINK
                Set-Watch
#>
        if ($__watcher) {
                $__watcher.EnableRaisingEvents = $false
                Write-Host "Отслеживание событий отключено" -f Yellow -b DarkGray
        }
}
 
set-alias watch Enable-Watch
function Enable-Watch() {
<#
        .SYNOPSIS
                Включает обработку событий
        .LINK
                Disable-Watch
        .LINK
                Remove-Watch
        .LINK
                Get-Watch
        .LINK
                Set-Watch
#>
        if ($__watcher) {
                $__watcher.EnableRaisingEvents = $true
                Write-Host "Отслеживание событий включено" -f Green -b DarkGray
        }
}
 
set-alias gwatch Get-Watch
function Get-Watch() {
<#
        .SYNOPSIS
                Получает сторожевой объект для установки новых свойств (если указаны)
                и возвращает его
        .EXAMPLE
                PS C:\> (gwatch).filter = "*.*"        # установить новый файловый фильтр
                PS C:\> gwatch -Filter *.*
        .EXAMPLE
                PS C:\> (gwatch).path= "c:\windows" # установить новую директорию для отслеживания
                PS C:\> gwatch -Path "c:\windows"
        .EXAMPLE
                PS C:\> gwatch -NotifyFilter "Filename,LastWrite,LastAccess" -Filter "*.*"
        .EXAMPLE
                PS C:\> gwatch -IncludeSubdirectories
                PS C:\> gwatch -IncludeSubdirectories:$false
        .OUTPUTS
                FileSystemWatcher
        .LINK
                Set-Watch
        .LINK
                Disable-Watch
        .LINK
                Remove-Watch
        .LINK
                Get-Watch
#>
        param(
                [string]$Path,
                [string]$Filter,
                [switch][Boolean]$IncludeSubdirectories,
                [string]$NotifyFilter
        )

        if ($__watcher -eq $null) {
                Write-Host "Объект FileSystemWatcher не определен" -f Red
        } else {
                $type_watcher = $__watcher.gettype()
                $MyInvocation.BoundParameters.GetEnumerator() | %{
                        $key = $_.Key
                        $value = $_.Value
                        if ($key -eq "NotifyFilter") {
                                $value = [IO.NotifyFilters]$value
                        }
                        if ($key -eq "IncludeSubdirectories") {
                                [Boolean]$value = $value
                        }
                        $prop = $type_watcher.GetProperty($key)
                        $prop.SetValue($__watcher, $value)
                }
                return $__watcher
        }
}

set-alias rwatch Remove-Watch
function Remove-Watch() {
<#
        .SYNOPSIS
                Удаляет задание по списку имен, либо все
        .EXAMPLE
                PS C:\> rwatch Created,Deleted        # удалить задания по именам
        .EXAMPLE
                PS C:\> rwatch                                        # удалить все задания
        .LINK
                Set-Watch
#>

        [CmdletBinding()]
        param(
                [string[]]$names
        )
       
        if ($names.Length -eq 0) {
                $names = (get-job).Name
        }

        foreach ($jobname in $names) {
                if ((get-job).Name -ccontains $jobname) {
                        Unregister-Event $jobname -Force
                        Remove-Job -Name $jobname -Force
                        Write-Host "Задание $jobname удалено" -f Green -b DarkGray
                } else {
                        Write-Host "Задание $jobname не найдено" -f Yellow -b DarkMagenta
                }
        }
        Set-Variable __watcher -Value $null -Scope Script
}


Было желание упростить немного, но может быть и не стоит изобретать велосипеды...


Время: 23:34.

Время: 23:34.
© OSzone.net 2001-