Задачка для ТС за деньги

Обсуждение любых программ, не имеющих отношения к Total Commander.

Модераторы: d-view, Моторокер, Avada, CaptainFlint, Nik

Аватара пользователя
Volniy
Сообщения: 585
Зарегистрирован: Ср дек 15, 2004 00:17
Откуда: Местный

Сообщение Volniy »

Batya писал(а):Так ведь lamicard написал, что после печати файл надо переместить в архивную папку. Соответственно, "как два пальца ..." :D
Ты опять упрощаешь. Между тем моментом, когда ты обнаружишь файл и когда ты его уже переместишь в некую другую папку пройдет существенный промежуток времени. В это время может появиться новый файл. Как ты об этом узнаешь в скрипте, он ведь будет все еще печатью предыдущего файла заниматься?
Batya писал(а):Дргое дело, что мне самому стало интересно, а как при этом работает DirMonitor? Он ведет лог обработанных файлов и хранит список где-то в файле или в собственной памяти? Как он отработает после перезапуска?
И зря не читаешь доки, тем более не смотришь исходники (там ксати, PowerBasic, для тебя будет все понятно). Там все по-взрослому, однако, никаких списков :). Запускается сервис с десятью (по максимуму) тредами, каждый вешает на свою директорию API функцию "ReadDirectoryChangesW" и когда та возвращает положительный результат (произошло некоторое изменение в перечне файлов отслеживаемой директории) выполняет указанную вами команду над файлом-источником изменений (в данной реализации сервиса только в момент добавления файла, но можно обрабатывать и удаление, переименование, изменение атрибутов и тп).

Как я вижу решение с печатью:
запускаем-таки процесс DirMonitor, предварительно указав ему (в его ини-файле) 10 наших директорий и для каждой из них отдельный скрипт (пакетный файл и тп). Скрипт в качестве параметра получит путь к новому файлу PDF. В скрипте: отсыл на печать (pdfp с ожиданием выполнения) и последующее перемещение файла в Отработанные (возможно, поторебуется контроль за именем файла на случай дубликатов по имени). На этом скрипт завершается (я бы еще и в некий общий лог файл добавил запись), но его новый экземпляр будет снова запущен при возникновении нового PDF файла в соответсвующей папке. И так по кругу, весь рабочий день, пока работники, ранее занимавшиеся печатью вручную, пьют пиво и режутся в Doom :wink:

А тулзу я эту раньше не видел, но, похоже, у меня у самого найдется парочку задачек для нее. А еще учитывая наличие сорца... :roll:
Аватара пользователя
Batya
Сообщения: 2236
Зарегистрирован: Ср дек 15, 2004 09:51
Откуда: Москва, Россия

Сообщение Batya »

Volniy писал(а):Ты опять упрощаешь. Между тем моментом, когда ты обнаружишь файл и когда ты его уже переместишь в некую другую папку пройдет существенный промежуток времени. В это время может появиться новый файл. Как ты об этом узнаешь в скрипте, он ведь будет все еще печатью предыдущего файла заниматься?
А зачем же усложнять? :)
У меня уже работает несколько таких скриптовых мониторов, и я не вижу особых проблем. Вот кусок кода, по которому принцип, я думаю будет понятен:

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

'Устанавливаем ключ реестра в рабочее состояние
MykeyValue = True
WSH.RegWrite MyKey, MykeyValue

Set oSD  = FSO.GetFolder(SourceDir)

'Бесконечный цикл (выход по изменению ключа реестра)
Do While MykeyValue
  Status = False 'Ключ наличия файлов для отправки
  'Сканирование каталога
  For Each F In oSD.Files
    'Если имя файла начинается с указанного префикса
    If InStr(1, F.Name, Prefix, 1) = 1 Then
      Status = True
      'Пишем в лог текущее время и имя файла
      If Time < CDate("10:00:00") Then
        OTL.WriteLine Date & " 0" & Time & " ->   Файл для отправки - " & F.Name
      Else
        OTL.WriteLine Now & " ->   Файл для отправки - " & F.Name
      End If

      ...

    End If
  Next

  ...

  'Пауза в мс
  WScript.Sleep Delay * 1000
  'Читаем реестр
  MykeyValue = WSH.RegRead(MyKey) 
Loop
А с видением решения с печатью я согласен. Только если использовать DirMonitor, я бы сделал не 10 скриптов, а один скрипт с доп. параметром, но это уже детали.
VadiMGP
Сообщения: 1625
Зарегистрирован: Ср мар 21, 2007 20:58

Сообщение VadiMGP »

Batya писал(а):а понять как работает Ghostscript+GSview я еще не успел. Позже обязательно попробую.
Ну разве что, любопытства ради. Заказчику же Акробат нужен. :) Но GSView для печати совсем не нужен - он только для просмотра.
Аватара пользователя
Volniy
Сообщения: 585
Зарегистрирован: Ср дек 15, 2004 00:17
Откуда: Местный

Сообщение Volniy »

Тогда вот такая заготовочка конечного скрипта, у меня все печатает. Операции чтения флага из реестра пока закоментировал, мешали мне.

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

Dim WSH, FSO
Set WSH = CreateObject("wscript.Shell")
Set FSO = CreateObject("scripting.filesystemobject")
Dim I, PrCmd, PDFFile
Const AlreadyPrinted="F:\pdf\AlreadyPrinted"

'Устанавливаем ключ реестра в рабочее состояние 
MykeyValue = True 
'WSH.RegWrite MyKey, MykeyValue 
PDFFolders = Array("F:\pdf\1", "F:\pdf\2") ' пишем столько папок, сколько нам нужно
Printers = Array("HP LaserJet 1020", "HP LaserJet 1020") ' соответствующие принтеры для каждой папки
If FSO.FolderExists(AlreadyPrinted & "\" & Month(Date)) = False Then _
   FSO.CreateFolder AlreadyPrinted & "\" & Month(Date)
'Бесконечный цикл (выход по изменению ключа реестра) 
Do While MykeyValue
   For I= LBound(PDFFolders) To UBound(PDFFolders)
      Set PDFFolder  = FSO.GetFolder(PDFFolders(I))
      PrCmd = (Printers(I))
      For Each PDFFile In PDFFolder.Files
        If UCase(FSO.GetExtensionName(PDFFile.Name))="PDF" Then 
           'Печать, как таковая с помошью pdfp или как-нить иначе
           'pdfp.exe [options] [drive:][path]<filename>
           WSH.Run "c:\pdfp.exe -p """ & PrCmd & """ """ & PDFFile.Path & """" , 1, True 
           ' тут команда перeименования и перемещения уже отпечатанного файла, например
           PDFFile.Name= PDFFile.Name & ".printed"
           PDFFile.Move AlreadyPrinted & "\"  & Month(Date) & "\" & FSO.GetBaseName(PDFFile.Name)
        End If
      Next
      Set PDFFolder  = Nothing
   Next
   'Пауза в мс (а нужна ли, работы ведь хватает:-)
   WScript.Sleep Delay * 1000 
   'Читаем реестр 
   'MykeyValue = WSH.RegRead(MyKey)
Loop
Set WSH = Nothing
Set FSO = Nothing
Последний раз редактировалось Volniy Пт апр 13, 2007 18:55, всего редактировалось 2 раза.
VadiMGP
Сообщения: 1625
Зарегистрирован: Ср мар 21, 2007 20:58

Сообщение VadiMGP »

Volniy писал(а):Тогда вот такая заготовочка конечного скрипта,
Если это конечный скрипт, то я позволю себе влезть с комментариями, ладно?
Если по каким-то причинам команда PDFFile.Move "F:\pdf\AlreadyPrinted" & PDFFile.Name не выполнится, то это чревато постоянной печатью этого файла в диком количестве экземпляров. Каждые х секунд.
Аватара пользователя
Volniy
Сообщения: 585
Зарегистрирован: Ср дек 15, 2004 00:17
Откуда: Местный

Сообщение Volniy »

VadiMGP писал(а):
Volniy писал(а):Тогда вот такая заготовочка конечного скрипта,
Если это конечный скрипт, то я позволю себе влезть с комментариями, ладно?
Если по каким-то причинам команда PDFFile.Move "F:\pdf\AlreadyPrinted" & PDFFile.Name не выполнится, то это чревато постоянной печатью этого файла в диком количестве экземпляров. Каждые х секунд.
Что значит не выполнится? С чего бы это? А вообще-то если обработки ошибок не будет, то скрипт попросту вылетит. Ничего там до посинения печататься не будет. Ну, коль есть какие сомнения, то добавить проверку после попытки перемещения, например:

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

If FSO.FileExists PDFFile.Path Then 
MykeyValue = False
MsgBox "Ошибочка, однако. Нету сил файл передвинуть :)"
End If
Таких проверок можно много насобачить. Например, если папка для распечатанного общая, то неплохо бы проверять на совпадение имен файлов и если нужно слегка переименовывать файл. Вообще-то всего не предусмотришь. А вдруг в принтере чего? А вдруг PDF файл битый на печать отправят? А вдруг диск переполнится? А вдруг...

Это уже не мои проблемы. Скрипт общему заданию полностью соответствует, только создайте ему все условия для работы.

PS Я ведь написал "заготовочка". Это еще не конечный скрипт. Я ведь его даже в работе еще не пробовал :oops:
VadiMGP
Сообщения: 1625
Зарегистрирован: Ср мар 21, 2007 20:58

Сообщение VadiMGP »

Вообще-то всего не предусмотришь.
Да я и не предлагал предусмотреть все. Но по-моему, ты не понял меня, я не критиковать а помочь хотел. Я сам программист и всегда за исполнителя больше переживаю. :) А мой опыт научил меня, что если программа не содержит никакого контроля ошибок, то в конечном итоге, это приводит для исполнителя к бОльшим потерям времени на разборки с заказчиком, нежели потери времени на реализацию, хотя бы, минимального контроля ошибок. Три строчки, которые ты привел сегодня могут снять кучу головной боли завтра.
Скрипт общему заданию полностью соответствует, только создайте ему все условия для работы.
Все верно, соответствует. Но когда в один прекрасный день тебе звонят и говорят "Твой скрипт не работает", то иногда приходится тратить порядочно усилий, чтобы доказать/объяснить, что это не по твоей вине и что ты не верблюд.
lamicard
Сообщения: 18
Зарегистрирован: Пт апр 06, 2007 07:13

Сообщение lamicard »

забыл сказать что лист печатается 4 минуты где то.. т.е. это не лазерник выплевывающий в минуту десятки копий. если брать по объему файла в спулере - мы стараемся что бы на одно задание больше 1 гб не висело - машины и сеть виснут. хотя купили более/менее продвинутую машинку.. вобщем тест сейчас сделаем кода - скажу что как получилось дословно..
Аватара пользователя
Batya
Сообщения: 2236
Зарегистрирован: Ср дек 15, 2004 09:51
Откуда: Москва, Россия

Сообщение Batya »

Volniy
Я же скажал - "как два пальца ..." :)
Для меня основная проблема, как я уже писал выше, это понять, насколько корректно у lamicard проходит печать, а он так и не ответил до сих пор.
Ну и, судя по всему, ты согласен, что такой скриптовый монитор имеет право на существование, и не обязательно использовать DirMonitor? ;)

Volniy, VadiMGP
По поводу проверки на перенос у меня мысли были. И я бы охватил перенос конструкцией типа

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

On Error Resume Next
PDFFile.Move "F:\pdf\AlreadyPrinted\" & PDFFile.Name
If Not (Err.Number = 0) Then
  ...
End If
On Error GoTo 0
И еще была мысль ввести многомерный (по количеству типов ошибок) массив флагов ошибок. Если при обработке файла в каталоге произошла какая-нибудь ошибка, взводим соответствующий (типу ошибке и каталогу) флаг и на следующем цикле вначале проверяем возможность дальнейшей работы (для каждого типа ошибки своя проверка). Но это пока только мысли, поскольку...

lamicard
Так что у тебя с печатью?!!!
Нет, я не сплю. Я просто медленно моргаю.
Аватара пользователя
Volniy
Сообщения: 585
Зарегистрирован: Ср дек 15, 2004 00:17
Откуда: Местный

Сообщение Volniy »

VadiMGP писал(а):Все верно, соответствует. Но когда в один прекрасный день тебе звонят и говорят "Твой скрипт не работает", то иногда приходится тратить порядочно усилий, чтобы доказать/объяснить, что это не по твоей вине и что ты не верблюд.
Я ведь тут всего-лишь так, рядом проходил, мне с заказчиком не общаться. А так, конечно, когда пишу что-то более-менее серьезно, то действительно стараюсь предусмотреть все будущие затыки. А вообще то чаще всего такие ошибки находятся и устраняются в процессе эксплуатации: всегда оказывается, что заказчик не сообщил исполнителю о некоторые нюансы использования софта.
lamicard писал(а):забыл сказать что лист печатается 4 минуты где то..
Вообще-то задание печати считается выполненным не тогда, когда выпозла распечатанная страница, а когда она помещена в спулер. Тоесть это может происходить быстрее, чем за 4 минуты. В любом случае, чтобы не перегружать можно создавать некоторые задержки между посылками документов на печать (кроме одной секунды, что указана сейчас).

Batya DirMonitor мне по-прежнему кажется более грамотным решением, там меньше шаманства. Что касется обработки ошибок, то пусть все-таки и впрямь сначала немножко попечатают. А вообще мы не можем даже обработать главное - ошибку печати. Кто его знает, напечаталось там что или нет, мы ведь просто послали команду на печать, обратной-то связи нетути.

PS А чтобы не напороться на дублирование имен в папке "AlreadyPrinted", можно сделать такую коррекцию кода:

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

PDFFile.Move "F:\pdf\AlreadyPrinted\[" & _
Hour(Now) & "_" & Minute(Now)  & "_" & Second(Now) & "]_" & PDFFile.Name
Заодно будет реализовано что-то вроде лога печати.

PPS А имя принтера нужно наверное обрамлять в кавычки (если пробелы там возможны).
Аватара пользователя
Batya
Сообщения: 2236
Зарегистрирован: Ср дек 15, 2004 09:51
Откуда: Москва, Россия

Сообщение Batya »

Хм, что-то мы "разошлись" :)
Уж слишком много идей при небольшой вводной информации.
Может быть заказчик все-таки постарается поставить грамотное ТЗ?
Нет, я не сплю. Я просто медленно моргаю.
VadiMGP
Сообщения: 1625
Зарегистрирован: Ср мар 21, 2007 20:58

Сообщение VadiMGP »

Volniy писал(а):Я ведь тут всего-лишь так, рядом проходил,
Какое совпадение! Я тоже! :)
А вообще то чаще всего такие ошибки находятся и устраняются в процессе эксплуатации: всегда оказывается, что заказчик не сообщил исполнителю о некоторые нюансы использования софта.
Ха, он мне будет рассказывать! У меня на поддержке похожая система уже семь лет. Там правда не печать, а другая обработка, но это неважно. Этакий монстр - перелопачивает десятки тысяч файлов в день. Первую пару лет только тем и занимались, что добавляли контроль ошибок.
Вообще-то задание печати считается выполненным не тогда, когда выпозла распечатанная страница, а когда она помещена в спулер.
Можно попробовать использовать прямую печать на принтер, не через спулер.
Batya писал(а):Хм, что-то мы "разошлись" :)
Да не, мы тут так, рядом проходили и потрепались. Знаешь, как это бывает - один кувалдой махает, а вокруг толпа на это смотрит и обсуждает: "И кувалда у него не по стандарту ISO, и замах не по циркулю, и вообще это кувалда для левшей." :)
По поводу проверки на перенос у меня мысли были.
Я бы еще сделал вот что - сразу после печати переименовать файл. Добавить расширение ".printed" или еще как-то, чтобы при любых обстоятельствах избежать повторной печати того же файла даже даже если перенос файла не пройдет.
И еще была мысль ввести многомерный (по количеству типов ошибок) массив флагов ошибок.
Хорошая мысль. Ну тогда я умолкаю, больше мне нечего добавить.
lamicard
Сообщения: 18
Зарегистрирован: Пт апр 06, 2007 07:13

Сообщение lamicard »

Скрипт запущен с расширением vbs

Option Explicit

Dim Acrobat, Printers, Drivers, Ports, Doc, WSH
'========= Изменяемые параметры =================================
Acrobat = "е:\Program Files\Adobe\Acrobat 7.0\Reader\AcroRd32.exe"
Printers = "\\ДИЗАЙН\EPSON Stylus Photo R220 Series"
Drivers = "EPSON Stylus Photo R220 Series"
Ports = "EPSON Stylus Photo R220 Series"
Doc = "C:\1.pdf"
'==================================================================

Set WSH = WScript.CreateObject("WScript.Shell")

WSH.Run """" & Acrobat & """ /t """ & Doc & """ " & Printers & _
" """ & Drivers & """ " & Ports, 6, False

Set WSH = Nothing
WScript.Quit


выдал сервер ошибку - посмотреть можно по ссылке:
http://lami.land.ru/1.jpg
Аватара пользователя
Batya
Сообщения: 2236
Зарегистрирован: Ср дек 15, 2004 09:51
Откуда: Москва, Россия

Сообщение Batya »

VadiMGP писал(а):Да не, мы тут так, рядом проходили и потрепались. Знаешь, как это бывает - один кувалдой махает, а вокруг толпа на это смотрит и обсуждает: "И кувалда у него не по стандарту ISO, и замах не по циркулю, и вообще это кувалда для левшей."
:D
Да ладно, что ж открещиваться-то? Я ж не собираюсь, действительно, деньги брать. Просто хочется помочь человеку. Что мы вместе, собственно, и делаем.

lamicard
У тебя пробел в имени принтера. Поэтому придется чуть-чуть поправить:

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

WSH.Run """" & Acrobat & """ /t """ & Doc & """ """ & Printers & _ 
""" """ & Drivers & """ " & Ports, 6, False
lamicard
Сообщения: 18
Зарегистрирован: Пт апр 06, 2007 07:13

Сообщение lamicard »

я могу конечное деньги себе оставить а Вам спасибо сказать.. но лучше давайте доведем до ума это решение а те 300 долл которые Вам не нужны куда скажете туда и перешлю - хоть в детский дом..

строку поменял та же беда - кажется либо неправильно драйвер указан или порт
Закрыто