PDA

Показать полную графическую версию : Открытие файлов по расширению не работает


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

Iska
21-06-2020, 23:07
ilayka, где расположен:
соответственно акробатом »
? Какого размера файлы? Как часто нужно проверять?

Fors1k
22-06-2020, 12:58
PowershellParam(
$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
Какого размера файлы? Как часто нужно проверять? »
Размер разный, проверять каждые 2 секунды. Расположение я написал выше...С:\PDF\

YuS_2
23-06-2020, 12:29
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
YuS_2, sleep не нужен

YuS_2
23-06-2020, 15:03
sleep не нужен »
писалось давно, уже точно не помню зачем впихнул sleep... что-то там в цикле подвисало, если не будет паузы короткой, вроде бы так. А так да, в принципе, не нужен он...

Fors1k
23-06-2020, 16:50
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
В waitforchanged следует передавать два параметра. »
хмм, совсем необязательно... waitforchanged (https://docs.microsoft.com/en-us/dotnet/api/system.io.filesystemwatcher.waitforchanged?view=netcore-3.1)

while(!($watcher.waitforchanged("created",1).Name)){} »
а это для чего?

gci $path *.pdf|? LastAccessTime -gt $d|%{&$_.FullName} »
- это лишнее. Каталог сканировать и фильтровать файлы по условию сравнения дат, тоже не требуется. Watcher сам всё сделает как надо.
При появлении нового файла, он будет отслежен по указанному событию (https://docs.microsoft.com/en-us/dotnet/api/system.io.watcherchangetypes?view=netcore-3.1) и результатом, уже будет объект, в котором содержится имя файла, его просто надо будет открыть. По условию задачи, этого достаточно.

Fors1k
23-06-2020, 17:36
хмм, совсем необязательно »
Необязательно, только тогда его остановить будет невозможно))
а это для чего? »
Это ожидание появления нового файла в папке.
Watcher сам всё сделает как надо. »
За watcher спасибо, но сделать все он не сможет. Сольно watcher подойдет для отслеживания либо одного файла, либо папки но на предмет факта изменений в ней. А нам нужно не только знать что в папке что-то произошло, но и узнать какие именно файлы были скопированы. Так, к примеру, если в папку скопировать 2 (или больше) файла, то watcher сообщит нам только об одном, а второй проскочит мимо нас.

YuS_2
23-06-2020, 21:26
Необязательно, только тогда его остановить будет невозможно)) »
а зачем его останавливать? Ну, даже если надо, то закрываем сессию и всё выключается...

Это ожидание появления нового файла в папке. »
Не совсем. Цикл там зачем?
Для ожидания, достаточно:
$watcher.waitforchanged("created")
и пока файл не появится, будет действовать ожидание...
или так:
$watcher.waitforchanged("created",-1)
а с таймаутом в 1 сек., ожидание, по факту, будет работать 1 сек. и продолжится цикл...

но сделать все он не сможет. »
В таком виде, да. Нужна подписка на события, тогда будет всё работать как надо и тогда этого:
если в папку скопировать 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
а зачем его останавливать? »
Например, что бы поправить что-то в коде. Что мне делать с этой (https://yadi.sk/i/qyQLt4w9X6_T8w) красотой? :)
Цикл там зачем?
Для ожидания, достаточно: »
Цикл нужен, если вызываем с таймаутом, который дает возможность нажать стоп.
Нужна подписка на события, тогда будет всё работать как надо »
Вот такой вариант - да, вопрос решает полностью :good:

YuS_2
24-06-2020, 08:05
Например, что бы поправить что-то в коде. »
Ну, даже если надо, то закрываем сессию и всё выключается... »
Как вариант... ибо при автоматизации слежения, паузы увеличивают вероятность пропуска фалов, либо получения ложных дубликатов...
В общем, не совсем корректная работа кода получается... с лишним сканированием каталога и доп. проверками.

Цикл нужен, если вызываем с таймаутом, который дает возможность нажать стоп. »
Рабочий код не будет ведь запускаться через 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
Спасибо всем. Но это п-шелл...к нему нужно еще батник с разрешением прикручивать. Отслеживание и авто-откр нужно делать на удаленной машине. В принципе прикрутить не сложно...однако я думал есть возможность только средствами бат файла, планировщика или микропрогой sleep реализовать.

Fors1k
25-06-2020, 16:02
YuS_2, раз уж пошла такая пьянка, давай замутим командлет ему))
Сделал вот такой набросок, пиши, если есть чего дополнить.
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
Fors1k, человек не хочет powershell, в принципе... сизифов труд, выполнять не хочется...
Ну, а если для себя, то в функцию старта, надо бы добавить проверки на правильные значения параметров и может быть, ещё и на наличие пути (если не указан, то текущий каталог) и т.п.
Сегодня, что-то думать нет особого желания... :)

Fors1k
25-06-2020, 17:47
Ну, а если для себя »Ага, для себя. Такая функция мне кажется весьма полезной)
Сегодня, что-то думать нет особого желания »Так тут же срочности нет ни какой. Задача эта так... лишь пища для ума, как развлечение)

YuS_2
25-06-2020, 20:52
пища для ума, как развлечение »
порылся тут на складе скриптов... попался готовый watchdog, слямзенный на киберфоруме, приведу полностью, как есть:
<# 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/library/system.io.filesystemwatcher(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
}
Было желание упростить немного, но может быть и не стоит изобретать велосипеды...




© OSzone.net 2001-2012