2013-10-08 2 views
3

Я все еще немного новичок в powershell (из vbscript), и прошло какое-то время, так как я сделал что-то слишком серьезное, поэтому заранее извиняюсь, если код не как изящное, как могло бы быть.Odd Copy-Item поведение powershell

Сценарий заключается в следующем:

Система используется создает папки в директории каждое полчаса, в этих подкаталогах файлы изображения могут быть созданы (они являются различными названиями, в подкаталоге, но та же условность поперек вложенные папки, поэтому SubFolderA может содержать picture1.jpg, picture2.jpg, picture3.jpg, но так могут быть и другие подпапки.

Мне нужно отслеживать все дерево и всякий раз, когда создается JPG-файл, переименуйте его на основе даты/времени/секунд и поместите его в «плоскую» папку.

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

Сценарий останавливается на «Я запускаю эту копию», но ничего не происходит, если я перезапущу скрипт, он работает нормально, пока изменения не появятся во второй папке. Это может быть любая папка, в которой происходят первые изменения, после чего появляется любая папка.

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

Дерево каталогов выглядит следующим образом:

X:\PicsSource 
X:\PicsSource\Folder 1\ 
X:\PicsSource\Folder 2\ 
X:\PicsSource\Folder 3\ 

Я должен также упомянуть, что источник будет сетевой ресурс и адресат будет локальным изначально, но также может быть доля сети в будущем. Для моего тестирования источником и назначением являются сетевые ресурсы (на одном сервере), причем сценарий выполняется на другом компьютере.

В каждой папке много файлов, но меня интересует только JPG.

код, который я до сих пор: (! Рад видеть улучшения, хотя)

Unregister-Event -SourceIdentifier FileCreated -ErrorAction SilentlyContinue 
$folder = 'X:\PicsSource\'  #Folder to monitor 
$destination = 'X:\PicsDest\' #Folder to copy files too 
$filter = '*.jpg'    #Set this for filtering of file types 


$fsw = New-Object IO.FileSystemWatcher $folder, $filter -Property @{ 
IncludeSubdirectories = $true    
NotifyFilter = [IO.NotifyFilters]'FileName, LastWrite' 
} 



$onCreated = Register-ObjectEvent $fsw Created -SourceIdentifier FileCreated -Action { 
$path = $Event.SourceEventArgs.FullPath 
$name = $Event.SourceEventArgs.Name 

$newname = get-item $path | Select @{Name="CreationTime";Expression= {"{0:yyyy}-{0:MM}-{0:dd}@{0:HH}{0:mm}_{0:ss}" -f ([DateTime]$_.CreationTime)}} 
#Write-host $newname 
$newname = $newname -replace "@{CreationTime=" 
$newname = $newname -replace "}" 
#Write-Host $newname 
#Write-Host $destination 
#Write-Host $path 
$finaldest = $destination + $newname 
$finaldest = $finaldest + ".JPG" | Out-String 
$finaldest = $finaldest.Trim() 
write-host $finaldest 
Copy-Item -path $path -Destination $finaldest -Force -Verbose 
} 

Строка CreationTime немного сумбурно, но ее функционал Я считаю

Заранее спасибо, я увлечена чтобы решить это :)

Приветствия, Matt

+0

Появляется ли сценарий в результате ошибки, или он продолжается после зависания? – Colyn1337

ответ

0

Моя догадка, что ваш блок скрипта для обработки созданного события бросает исключение, и FileSystemWatcher никогда не вызывает его снова. Любое необработанное исключение, возникающее из этого события, приведет к тому, что FileSystemWatcher никогда не вызовет ваше событие снова.

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

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

$onCreated = Register-ObjectEvent $fsw Created -SourceIdentifier FileCreated -Action { 
    $path = $Event.SourceEventArgs.FullPath 

    $newname = (Get-Item $path).CreationTime.ToString("[email protected]_ss_fff") 
    $finaldest = $destination + $newname + ".JPG" 

    $copied = $false 
    $retriesLeft = 10 
    while(-not $copied -and ($retriesLeft -gt 0)) { 
     try { 
      Copy-Item -path $path -Destination $finaldest -Force -Verbose 
      $copied = $true 
     } catch { 
      Start-Sleep -Milliseconds 500 
      --$retriesLeft 
     } 
    } 
    if (-not $copied) { 
     # log an error with $path and $finaldest 
    } 
} 

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

Смежные вопросы