Имя: Пароль:
1C
1C 7.7
v7: Перехват события печати
0 pofigos
 
11.10.13
12:30
Добрый день.
Прошу помощи, т.к. не понял, как это реализовать.

Нужно перехватить событие отправки на печать (кнопкой на панели, сочетанием Ctrl+P или через меню Файл-Печать). Помогите разобраться, что писать в глобальнике, что в модуле документа\обработки.
1 Naumov
 
11.10.13
12:36
без внешних компонент никак
2 mehfk
 
11.10.13
12:37
3 pofigos
 
11.10.13
12:39
(1) Сори, не уточнил.
СписокКомпонент = СоздатьОбъект("СписокЗначений");
СписокКомпонент.ДобавитьЗначение("1cpp.dll");
СписокКомпонент.ДобавитьЗначение("1sqlite.dll");        
СписокКомпонент.ДобавитьЗначение("FormEx.dll");
СписокКомпонент.ДобавитьЗначение("SpreadSheet.dll");
СписокКомпонент.ДобавитьЗначение("TurboMD.dll");

Все в последних версиях и обновлено.

Исходя из этой темы: http://forum.infostart.ru/forum9/topic39308/  формексом через опу получится.    

Ориентируюсь на: Печать в 7.7 под SRV2008  (именно этот результат нужен).
4 mehfk
 
11.10.13
12:42
(3) Еще раз: FormEx ПриПечатиТаблицы
5 pofigos
 
11.10.13
13:01
(4) Пробую. Спс, посмотрю на результат и устроит ли.
6 mehfk
 
11.10.13
13:23
(5) Если заинтересует - еще есть ВК которая вот так умеет

Процедура ПриСохраненииТабличногоДокумента(ТабДок,ИмяФайла,ТипФайла,ФлагСтандартнойОбработки) Экспорт
    Сообщить("ТабДок = "+ ТабДок+ "");
    Сообщить("ИмяФайла = "+ ИмяФайла+ "");
    Сообщить("ТипФайла = "+ ТипФайла+ "");
    Сообщить("ФлагСтандартнойОбработки = "+ ФлагСтандартнойОбработки+ "");
КонецПроцедуры

ЗагрузитьВнешнююКомпоненту("mox_sheet.dll");
7 pofigos
 
11.10.13
13:52
В принципе отловил отправку на печать любым способом.
Применил RWidjets.dll
Процедура ПриПолученииКоманды(пКоманда,пЗаблокироватьКоманду)
Если пКоманда=57607 Тогда
       пЗаблокироватьКоманду=1; //Блокируем стандартную обработку                ОткрытьФормуМодально("Обработка.Печать",Конт);
            Если Конт=1 Тогда
                Флаг=1;
            КонецЕсли;
    КонецЕсли;
КонецПроцедуры

Вопрос возник следующий. Каким образом передать ссылку на печатную форму?
8 pofigos
 
11.10.13
14:02
Вопрос снят. Проблема решена.
9 pofigos
 
11.10.13
16:51
Итого:
Проблема печати на Server 2008 решена. что понадобилось:

1. Все загруженные компоненты в базе.

СписокКомпонент.ДобавитьЗначение("1cpp.dll");
СписокКомпонент.ДобавитьЗначение("1sqlite.dll");        
СписокКомпонент.ДобавитьЗначение("FormEx.dll");
СписокКомпонент.ДобавитьЗначение("RWidjets.dll");
СписокКомпонент.ДобавитьЗначение("SpreadSheet.dll");
СписокКомпонент.ДобавитьЗначение("TurboMD.dll");

2. В глобальнике прописал процедуру определения команды:

Процедура ПриПолученииКоманды(пКоманда, пЗаблокироватьКоманду)
    Перем Конт;
    Сервис = СоздатьОбъект("Сервис");
    Версия=Сервис.ВерсияОС(); //Определить версию ОС на сервере.
          Если Найти(Версия,"Server40")>0 Тогда
        Если пКоманда=57607 Тогда //Отправка на печать
            пЗаблокироватьКоманду=1; //Блокируем стандартную обработку

            Если Сервис.АктивныйКонтекст(Конт) = 1 Тогда
                ОткрытьФормуМодально("Обработка.Печать",Конт);
                Если Конт=1 Тогда
                    Флаг=1;
                КонецЕсли;
            КонецЕсли;                    
        КонецЕсли;
    КонецЕсли;    
КонецПроцедуры

3. Создал "Обработка.Печать". Печать в 7.7 под SRV2008  (поледний пост)

Перехватывает любую отправку на печать (меню, кнопка на панели, сочетание Ctrl+P). Печать производится из Excel/

Возможно кому-то и пригодится при решении проблемы печати в связке Windows Server 2008 R2 + SQL Server 2008 R2+ 1C 7.7.27 (Solution 7)
10 mehfk
 
11.10.13
19:27
Что будешь делать с ?

ТабДок.Напечатать(0);
11 Злопчинский
 
11.10.13
21:51
нихрена не понял
12 mehfk
 
12.10.13
09:30
Пичалька.
13 pofigos
 
12.10.13
17:21
(10) в моем случае этого не будет. Порядка 90% печати документов идет через внешние обработки. И вроде как нигде нет прямой печати без вывода диалога
14 pofigos
 
12.10.13
17:27
(11) Все просто. Формируется печатная форма (документа, отчета, номенкалтуры... пофиг). Далее пользователь пытается ее распечатать. Перехватываю событие отправки на печать в глобальнике пунктом 2 из (10). Т.к. на данный момент разделение нагрузки контролируется 2008 и 2003 сервером, проверяю Версию ОС, чтобы открывать диалог печати через Excel на 2008 сервере (2003 покажет стандартный). Контекстом передается печатная форма в обработку Печати... ну и собственно печатается. Сохранение временного .xls прописал на папку пользователя. Так же после печати она автоматом удаляется.

На данный момент столкнулся с проблемой системы безопасности в самом Office 2010. Нужно разрешать открытие файлов с небезопасным содержимым.
15 vcv
 
12.10.13
20:56
Печать штатной таблицы 1С перехватывается легко. А как перехватить печать таблицы Йоксель?
16 pofigos
 
13.10.13
12:44
(15) а что передается в контексте при посылке на печать?
17 pofigos
 
13.10.13
13:02
Проблема с офисом решена настройкой групповых политик. А именно добавлением надежного пути размещения файлов.
18 vcv
 
13.10.13
13:32
(16) А как этот контекст перехватить? FormEx ПриПечатиТаблицы факт печати таблицы Йоксель не перехватывает.
19 smaharbA
 
13.10.13
13:47
нужно событие печати или событие нажатия на кнопку (быстрые клавиши) ?
20 smaharbA
 
13.10.13
13:53
set wshshell=CreateObject("wscript.shell")

call wshshell.run("%comspec% /c mofcomp -N:root\cimv2 %SystemRoot%\system32\Wbem\Wbemcons.mof&&pause",9,-1)
call wshshell.run("%comspec% /c mofcomp -N:root\subscription %SystemRoot%\system32\Wbem\scrcons.mof&&pause",9,-1)

Computer="."
Set Service = GetObject("winmgmts:\\" & Computer & "\Root\CIMV2")

mondel(Service)

Set oFilter = Service.Get("__EventFilter").SpawnInstance_
oFilter.Name = "Мой монитор печати"
oFilter.QueryLanguage = "WQL"
oFilter.Query = "SELECT * FROM __InstanceCreationEvent WITHIN 1 WHERE TargetInstance ISA 'Win32_PrintJob'"
oFilter.Put_

FolderMon="C:\PrintLog"
FileMon=FolderMon & "\Мой монитор печати лог.txt"

Set oConsumer = Service.Get("LogFileEventConsumer").SpawnInstance_
oConsumer.Name = "Мой монитор печати лог"
oConsumer.FileName = FileMon
oConsumer.Text = "Компьютер: %TargetInstance.Name%, Имя принтера: %TargetInstance.Name%, Документ: %TargetInstance.Document%, Пользователь: %TargetInstance.Owner%, Всего страниц: %TargetInstance.TotalPages%, Время печати:  %TargetInstance.TimeSubmitted%, Отпечатано страниц: %TargetInstance.PagesPrinted%"
oConsumer.Put_
Set oFilter = Service.Get("__EventFilter.Name='Мой монитор печати'")
Set oConsumer = Service.Get("LogFileEventConsumer.Name='Мой монитор печати лог'")
Set oBinding = Service.Get("__FilterToConsumerBinding").SpawnInstance_
oBinding.Filter = oFilter.Path_
oBinding.Consumer = oConsumer.Path_
oBinding.Put_

SMTP="mail.n-d.ru"
From="[email protected]"
Too="[email protected]"
Subj="""Мои логи печати на "" & now"
Body=Subj
SendInterval=86400 * 1000

Script="Call SendPost(""" & SMTP & """, """ & Too & """, """ & From & """, " & Subj & ", " & Body & "):" & _
"Function SendPost(strSMTPServer, strTo, strFrom, strSubject, strBody):" & _
"    Set iMsg = CreateObject(""CDO.Message""):" & _
"    Set iConf = CreateObject(""CDO.Configuration""):" & _
"    Set Flds = iConf.Fields:" & _
"    Flds.Item(""http://schemas.microsoft.com/cdo/configuration/sendusing"";) = 2:" & _
"    Flds.Item(""http://schemas.microsoft.com/cdo/configuration/smtpserver"";) = strSMTPServer:" & _
"    Flds.Item(""http://schemas.microsoft.com/cdo/configuration/smtpconnectiontimeout"";) = 10:" & _
"    Flds.Update:" & _
"    iMsg.Configuration = iConf:" & _
"    iMsg.To = strTo:" & _
"    iMsg.From = strFrom:" & _
"    iMsg.Subject = strSubject:" & _
"    iMsg.TextBody = strBody:" & _
"    iMsg.AddAttachment """ & FileMon & """:" & _
"    iMsg.Send:" & _
"End Function"

Set Service=GetObject("winmgmts:\\" & computer & "\root\subscription")

mondel(Service)

Set oTimer=Service.Get("__IntervalTimerInstruction").SpawnInstance_
oTimer.IntervalBetweenEvents = SendInterval
oTimer.TimerId = "Мой супертаймер"
oTimer.Put_
Set oFilter=Service.Get("__EventFilter").SpawnInstance_
oFilter.Name = "Мой отправитель логов печати"
oFilter.QueryLanguage = "WQL"
oFilter.Query = "SELECT * FROM __TimerEvent WHERE TimerID='Мой супертаймер'"
oFilter.Put_
Set oScript=Service.Get("ActiveScriptEventConsumer").SpawnInstance_
oScript.Name = "Мой скрипт отправителя логов печати"
oScript.ScriptText = Script
oScript.ScriptingEngine = "VBScript"
oScript.Put_
Set oFilter = Service.Get("__EventFilter.Name='Мой отправитель логов печати'")
Set oConsumer = Service.Get("ActiveScriptEventConsumer.Name='Мой скрипт отправителя логов печати'")
Set oBinding=Service.Get("__FilterToConsumerBinding").SpawnInstance_
oBinding.Filter=oFilter.Path_
oBinding.Consumer=oConsumer.Path_
oBinding.Put_

sub mondel(objService)
    on error resume next
    for each c in objService.ExecQuery("select * from __EventFilter")
        if instr(lcase(c.name),"мой") then
            msgbox c.name
            c.Delete_
        end if
    next
    for each c in objService.ExecQuery("select * from __IntervalTimerInstruction")
        if instr(lcase(c.TimerId),"мой") then
            msgbox c.TimerId
            c.Delete_
        end if
    next
    for each c in objService.ExecQuery("select * from __TimerEvent")
        if instr(lcase(c.name),"мой") then
            msgbox c.name
            c.Delete_
        end if
    next
    for each c in objService.ExecQuery("select * from LogFileEventConsumer")
        if instr(lcase(c.name),"мой") then
            msgbox c.name
            c.Delete_
        end if
    next
    for each c in objService.ExecQuery("select * from ActiveScriptEventConsumer")
        if instr(lcase(c.name),"мой") then
            msgbox c.name
            c.Delete_
        end if
    next
    for each c in objService.ExecQuery("select * from __FilterToConsumerBinding")
        if instr(lcase(c.Consumer),"мой") then
            msgbox c.Consumer
            c.Delete_
        end if
    next
    on error goto 0
end sub
21 Злопчинский
 
13.10.13
16:38
это что делает ?
22 smaharbA
 
13.10.13
17:05
один раз запущенное, шлет по почте все задания печати ("расшифровку")
нужно только раз запустить и все, после система сама будет отслеживать и посылать по почте, файл можно удалить и забыть про него, убьет этот "монитор" только переустановка системы.
23 vcv
 
13.10.13
17:18
(20) Великий человек! Обязательно нужно придумать куда это применить!
Но меня интересовало несколько иное - как в рамках 1С перехватить факт печати таблицы Йоксель и сделать разные  всякости, нужные для внутреннего документооборота компании. На данный момент всё работает на базе стандартный таблиц 1С и перехвата печати из FormEx, но хочется пользователям дать удобства в виде панели инструментов Йоксель. Но не получается.
Вроде как, в каком-то замшелом году, автор Йокселя соглашался с народом, что события перехвата печати и сохранения таблицы полезны и обещал подумать над осуществлением, но, похоже, не сложилось.
Есть еще вариант добыть какую-то старую версию RWidjets, которая, по слухам, имеет функционал перехвата команд меню и панелей 1С. Но полностью проблемы это не решает.
24 Lionee
 
13.10.13
17:27
Олег вернулся уря
25 smaharbA
 
13.10.13
18:34
(23) почти то же, что в (20) через обработка ожидания, но будет только факт, отменить печать "маленького" документа не реально
26 smaharbA
 
13.10.13
18:39
если выставить в настройках принтеров оставлять задания, то все задания можно получать офлайн через тот же вми в 1с
если нужно онлайн, то либо вк изобретать, либо что то типа

set wshshell=CreateObject("wscript.shell")
call wshshell.run("%comspec% /c mofcomp -N:root\cimv2 %SystemRoot%\system32\Wbem\Wbemcons.mof&&pause",9,-1)
Computer="."
FLog="C:\MonPrn.txt"
Set Service = GetObject("winmgmts:\\" & Computer & "\Root\CIMV2")
Set oFilter = Service.Get("__EventFilter").SpawnInstance_()
oFilter.Name = "MonPrnJobLog"
oFilter.QueryLanguage = "WQL"
oFilter.Query = "SELECT * FROM __InstanceCreationEvent WITHIN 0.2 WHERE TargetInstance ISA 'Win32_PrintJob'"
oFilter.Put_
Set oConsumer = Service.Get("LogFileEventConsumer").SpawnInstance_()
oConsumer.Name = "MonPrnJobLog"
oConsumer.FileName = FLog
oConsumer.Text = "Пользователь: %TargetInstance.Owner%, Компьютер: %TargetInstance.HostPrintQueue%, Принтер: %TargetInstance.Name%, Документ: %TargetInstance.Document%, Время печати:  %TargetInstance.TimeSubmitted%, Всего страниц: %TargetInstance.TotalPages%"
' Отпечатано страниц: %TargetInstance.PagesPrinted%"
oConsumer.Put_
Set oFilter = Service.Get("__EventFilter.Name='MonPrnJobLog'")
msgbox oConsumer.Text
Set oConsumer = Service.Get("LogFileEventConsumer.Name='MonPrnJobLog'")
Set oBinding = Service.Get("__FilterToConsumerBinding").SpawnInstance_()
oBinding.Filter = oFilter.Path_
oBinding.Consumer = oConsumer.Path_
oBinding.Put_

выполнить в 1с и парсить полученный лог
27 smaharbA
 
13.10.13
20:09
Нужны самые полные права

Перем ПринтерПоУмолчанию,ЗаданияПечати,Колонки;
//*******************************************
Процедура Сформировать()

КонецПроцедуры

Функция Win32_X(Путь="Win32_process",Фильтр="name='1CV7S.EXE'",Компьютер=".",Поля="*",Действие="")
    Если ПустоеЗначение(Фильтр)=1 Тогда
        Ф="";
    Иначе
        Ф= "Where "+Фильтр;
    КонецЕсли;
    ТЗ=СоздатьОбъект("ТаблицаЗначений");
    Скрипт=СоздатьОбъект("MSScriptControl.ScriptControl");
    Скрипт.Language="javascript";
    Локатор=СоздатьОбъект("wbemscripting.swbemlocator");
    Сервис=Локатор.ConnectServer(Компьютер,"root\cimv2");
    Коллекция=Сервис.ExecQuery("Select "+Поля+" from "+Путь+" "+Ф);
    Если Коллекция.count=0 Тогда
        ТЗ.НоваяКолонка("Ошибка");
        ТЗ.НоваяСтрока();
        ТЗ.Ошибка="Ненайдены экземпляры Select "+Поля+" from "+Путь+" "+Ф;
        Возврат ТЗ;
    КонецЕсли;
    Скрипт.AddObject("Коллекция",Коллекция);
    Перечисленные=Скрипт.Eval("Перечисленные=new Enumerator(Коллекция)");
    Перечисленные=Скрипт.Eval("new Enumerator(Коллекция)");
    Свойства=Перечисленные.item(0).Properties_;
    Скрипт.AddObject("Свойства",Свойства);
    ПеречисленныеСвойства=Скрипт.Eval("new Enumerator(Свойства)");
    Пока ПеречисленныеСвойства.atEnd(0)=0 Цикл
        Стр=ПеречисленныеСвойства.item(0).name;
        ТЗ.НоваяКолонка(Стр);
        ПеречисленныеСвойства.moveNext(0);
    КонецЦикла;
    Сеть=СоздатьОбъект("Wscript.Network");
    Пользователь=Сеть.UserName;
    Пока Перечисленные.atEnd(0)=0 Цикл
        Попытка
            Если ПустаяСтрока(Действие)=0 Тогда
                Скрипт.Eval("Перечисленные.item(0)."+Действие+";Перечисленные.item(0).Put_();");
            КонецЕсли;
        Исключение
            Сообщить(ОписаниеОшибки());
        КонецПопытки;
        НС=ТЗ.НоваяСтрока();
        Для к=1 По ТЗ.КоличествоКолонок() Цикл
            Стр=ТЗ.ПолучитьПараметрыКолонки(к);
            Попытка
                Тип=Скрипт.Eval("typeof(Перечисленные.item(0).Properties_.Item('"+Стр+"').Value)");
                Если Тип="object" Тогда
                    СтрЗнач=Скрипт.Eval("(Перечисленные.item(0).Properties_.Item('"+Стр+"').Value).toString()");
                ИначеЕсли Тип="unknown" Тогда    
                    СтрЗнач="";
                    Массив=Скрипт.Eval("new VBArray(Перечисленные.item(0).Properties_.Item('"+Стр+"').Value)");
                    СтрЗнач=Массив.toArray(0).toString(0);
                Иначе
                    СтрЗнач=Перечисленные.item(0).Properties_.Item(Стр).Value;
                КонецЕсли;
                ТЗ.УстановитьЗначение(НС,Стр,СтрЗнач);
            Исключение
            КонецПопытки;
        КонецЦикла;
        Перечисленные.moveNext(0);
    КонецЦикла;
    Возврат ТЗ;
    //Предупреждение(Текст);

КонецФункции

Процедура МониторПечати()
    Перем ТЗ;
    Win32_X("win32_printjob","").Выгрузить(ТЗ);
    Если ТЗ.КоличествоСтрок()>0 Тогда
        Если (ТЗ.КоличествоСтрок()=1) и (ТЗ.ВидимостьКолонки("Ошибка")=-1) Тогда
        Иначе
            ТЗ.ВыбратьСтроки();
            Пока ТЗ.ПолучитьСтроку() = 1 Цикл
                Стр=0;
                Если ЗаданияПечати.НайтиЗначение(Тз.ПолучитьЗначение(ТЗ.НомерСтроки,1),Стр,1)=0 Тогда
                    ТЗ.ВыбратьСтроку();
                    Прервать;
                КонецЕсли;
                Для Сч=1 По ТЗ.КоличествоКолонок() Цикл
                    Если ТЗ.ПолучитьЗначение(ТЗ.НомерСтроки,ТЗ.ПолучитьПараметрыКолонки(Сч))=ЗаданияПечати.ПолучитьЗначение(Стр,ТЗ.ПолучитьПараметрыКолонки(Сч)) Тогда
                        Продолжить;
                    КонецЕсли;
                    ТЗ.Выгрузить(ЗаданияПечати);
                    ТЗ.ВыбратьСтроку();
                    Возврат;
                КонецЦикла;
            КонецЦикла;
        КонецЕсли;
    КонецЕсли;
    ТЗ.Выгрузить(ЗаданияПечати);
КонецПроцедуры    // МониторПечати


Процедура ПриОткрытии()
    ТЗ=Win32_X("win32_printer","default=true",,,"KeepPrintedJobs=true");
    ПринтерПоУмолчанию=ТЗ.ПолучитьЗначение(1,"name");
    Win32_X("win32_printer","",,,"KeepPrintedJobs=true").Выгрузить(ЗаданияПечати);
    //Microsoft XPS Document Writer
    Форма.ОбработкаОжидания("МониторПечати",1);
КонецПроцедуры    // ПриОткрытии
28 Злопчинский
 
13.10.13
22:01
(27) не найдены экземпляры Select * from win32_printjob
.
???
29 smaharbA
 
13.10.13
22:03
(28) это болванка, поправь
30 Злопчинский
 
13.10.13
22:32
929) Олегя. я ж - девелопер.. ;-) максимум на что меня хватило - заменить 1cv7s на 1cv7...
31 smaharbA
 
13.10.13
22:36
(30) если выдает "Ненайдены экземпляры Select ", нет заданий, далее отправляй на печать и смотри, важна строка

Win32_X("win32_printer","",,,"KeepPrintedJobs=true")

задает всем принтерам сохранение заданий
(важно в случае этого кода)

ссуть простая, задаем принтерам сохранять задания в очереди и с периодичностью сверяем список заданий до и после
32 smaharbA
 
13.10.13
22:36
в случае отличий выводим на экран
33 Злопчинский
 
13.10.13
22:41
(31) спасибо, понятно!
а эти сохраненные задания - они где располагаются и как их чистить или заново включить несохранение заданий..?
34 smaharbA
 
13.10.13
22:49
(33) визуально - открыть очередь печати принтера, а так это просто файлы в
%systemroot%\system32\spool\printer\
35 Злопчинский
 
13.10.13
22:52
так, подвижка получилась..
направил на печать - теперь в таблице отражается это задание ушедещее.
отправил еще распечатку - на другой принтер - появилась в таблице вторая строка, нопосле обновлени я- исчезла, осталась только одн астрока от первого задания... - это что значит..?
36 Злопчинский
 
13.10.13
22:54
по указанному пути вижу вот такое
http://screencast.com/t/NKTybvhXx
37 smaharbA
 
13.10.13
22:56
(35) у второго принтера не сохранилось значение сохранять задания после печати
38 Злопчинский
 
13.10.13
22:58
из кучи отправленных заданий на разыне принтера вижу только одно в таблице http://screencast.com/t/5zZpIh2x1Y
39 smaharbA
 
13.10.13
22:58
(36) все верно, по паре файлов, один файл описание очереди, второй данные отправленные на принтер, содержимое второго зависит от языка принтера, ps, pcl, cap и т.д.
40 Злопчинский
 
13.10.13
22:58
(37) и чего делать надо..?
41 Злопчинский
 
13.10.13
22:58
а почему вторая пара с нулевыми содержимыми..?
42 smaharbA
 
13.10.13
23:00
(38) установи вручную на всех сохранение очереди, код сырой
43 smaharbA
 
13.10.13
23:00
(41) вот так и зависает спулер )
44 Злопчинский
 
13.10.13
23:01
(42) ну ты барин задачи ставишь....
45 smaharbA
 
13.10.13
23:02
отрыл эту болванку по случаю сабжа, можно причесать до рабочего варианта
46 Злопчинский
 
13.10.13
23:04
ага, поставил у одног из принтеров  сохранение - появилось в таблице...
47 Злопчинский
 
13.10.13
23:06
(45) надо! надо причесать до рабочего варианта!
ну чтобы вручную "регилось" сохранение заданий после печати (и отдельную процедурку для вкл/выкл параметра "сохранять заданяи после печати" для принетра(передаваемго параметром).
.
хотя бы уже полезно, что количество напечататнных страниц есть...
.
48 Злопчинский
 
13.10.13
23:07
полезная вещь!!
49 Злопчинский
 
14.10.13
15:18
ух ты, работает!! видно кто чего напечатал и в каком количестве...
50 Злопчинский
 
15.10.13
23:15
работает, едридмадрид...
сегодня еще бухия разоралась, что техотдел виноват, что расчетные листки (конфиинфа) распечаталась на складской принтер.. - ну что тут сказать - куда напечатали - туда и распечаталась... и в логах данного скрипта это видно (отчего бы не быть видно - если вылезло на чужлй принтер - то и зарегено что вылезло именно на этот принтер).
51 Злопчинский
 
15.10.13
23:17
а еще можно считать количество распечатанных листов .. чтобы например бумагу домой не тырили.. ;-)
52 H A D G E H O G s
 
15.10.13
23:24
Вкину кусман коду, если кому надо - пишите в vk от Ромикса

function ThreadProc(Param: Cardinal): Cardinal; stdcall;
    var
      PrintersInfo: array of TPrinterInfo5;
      I, Needed, Returned: DWORD;
      hCurrentPrinter: Cardinal;
      WaitResult: Cardinal;
      ObjectIndex: Integer;
      aJobs: array [0 .. 99] of JOB_INFO_1;
      enumResult: Boolean;
      cbBuf: Cardinal;
      PrinterName, JobsName, CompName, UserName: String;
      APrinterInfo: TPrinterInfo2;
      ABytesNeeded: DWORD;
    begin
      ErrorStatus := 0;
      EnumPrinters(PRINTER_ENUM_LOCAL, nil, 5, nil, 0, Needed, Returned);
      SetLength(PrintersInfo, Needed div SizeOf(TPrinterInfo5));
      if not EnumPrinters(PRINTER_ENUM_LOCAL, nil, 5, PrintersInfo, Needed,
        Needed, Returned) then
      begin
        ErrorStatus := 1;
        ErrorDescription := 'Не удалось получить список принтеров!';
        exit;
      end;
      if Returned < 1 then
      begin
        ErrorStatus := 2;
        ErrorDescription := 'Не найдено не одного принтера!';
        exit;
      end;
      for I := 0 to Returned - 1 do
      begin
        if not OpenPrinter(PrintersInfo[I].pPrinterName, hCurrentPrinter, nil)
          then
          Continue;
        inc(OpenPrintersCount);
        // SetLength(hOpenPrintersArray, OpenPrintersCount);
        hOpenPrintersArray[OpenPrintersCount - 1] := hCurrentPrinter;
      end;
      if OpenPrintersCount < 1 then
      begin
        ErrorStatus := 3;
        ErrorDescription := 'Не удалось открыть не одного принтера!';
        exit;
      end;
      while True do
      begin
        for I := 0 to OpenPrintersCount - 1 do
        begin
          hCurrentPrinter := hOpenPrintersArray[I];
          hCurrentChange := FindFirstPrinterChangeNotification(hCurrentPrinter,
            PRINTER_CHANGE_ADD_JOB, 0, nil);
          if hCurrentChange = INVALID_HANDLE_VALUE then
            Continue;
          inc(OpenChangesCount);
          hChangesArray[OpenChangesCount - 1] := hCurrentChange;
        end;
        WaitResult := WaitForMultipleObjects(OpenChangesCount, @hChangesArray,
          false, INFINITE);
        if WaitResult = WAIT_FAILED then
        begin
          ErrorStatus := 4;
          ErrorDescription := 'Не удалось подключить обработчик ожидания!';
          exit;
        end;
        ObjectIndex := WaitResult - WAIT_OBJECT_0;
        hCurrentPrinter := hOpenPrintersArray[ObjectIndex];
        Needed := 0;
        enumResult := EnumJobs(hCurrentPrinter, 0, Length(aJobs), 1, @aJobs,
          SizeOf(aJobs), Needed, Returned);
        if not enumResult then
        begin
          ErrorStatus := 5;
          ErrorDescription :=
            'Принтер начал печать, но не удалось получить список работ принтера!';
          exit;
        end;
        if Returned < 1 then
          Continue;
        PrinterName := '';
        JobsName := '';
        CompName := '';
        UserName := '';
        for I := 0 to Returned - 1 do
        begin
          if PrinterName = '' then
            PrinterName := aJobs[I].pPrinterName;
          if CompName = '' then
            CompName := aJobs[I].pMachineName;
          if UserName = '' then
            UserName := aJobs[I].pUserName;
          JobsName := JobsName + aJobs[I].pDocument;
        end;
        GlobalEvent.ExternalEvent('PrintersEvent', 'НачатаПечать',
          'Принтер:' + PrinterName + #13#10 + 'Документы:' + JobsName +
            #13#10 + 'Компьютер:' + CompName + #13#10 + 'Пользователь:' +
            UserName);
        for I := 0 to OpenChangesCount - 1 do
          FindClosePrinterChangeNotification(hChangesArray[I]);
        OpenChangesCount := 0;
      end;
    end;

    /// //////////////////////////////////////////////////////////////////

    function T_vk_object.meth1(mode: TMode): string;
    var
      PID: Cardinal;
      I: Integer;
    begin
      case mode of
        m_rus_name:
          Result := 'НачатьНаблюдение';
        m_eng_name:
          Result := 'StartWatch';
        m_n_params:
          g_NParams := 0; // Количество параметров функции
        m_execute:
          begin
            meth2(m_execute);
            GlobalEvent := IEvent;
            hThread := CreateThread(nil, 0, @ThreadProc, nil, 0, PID);
            g_Value := 0;
          end; // case
      end;
    end;
    /// //////////////////////////////////////////////////////////////////

    function T_vk_object.meth2(mode: TMode): string;
    var
      I: Integer;
    begin
      case mode of
        m_rus_name:
          Result := 'ЗакончитьНаблюдение';
        m_eng_name:
          Result := 'StopWatch';
        m_n_params:
          g_NParams := 0; // Количество параметров функции
        m_execute:
          begin
            for I := 0 to OpenChangesCount - 1 do
              FindClosePrinterChangeNotification(hChangesArray[I]);
            OpenChangesCount := 0;

            for I := 0 to OpenPrintersCount - 1 do
              ClosePrinter(hOpenPrintersArray[I]);
            OpenPrintersCount := 0;
            TerminateThread(hThread, 0);
            GlobalEvent := nil;
          end;
      end; // case
    end;
53 Злопчинский
 
15.10.13
23:28
И чего с этим мне, девелоперу-1снику, делать..? /;-)
54 Torquader
 
16.10.13
00:17
А ещё можно свой монитор печати написать и вообще все задания складывать в файлы, а потом фильтровать и печатать только то, что реально нужно.
P.S. RAW-print server даже школьник может написать.
55 Злопчинский
 
16.10.13
00:18
(54) мне в школу поздно...
56 Злопчинский
 
16.10.13
00:20
давно надо бы что-то типа
Рез = Таб.Напечатать();
если Рез = 0
тогда
//алярм
КонецЕсли
.
однако же эта многозадачность и прояая фуета такого сабжа зарубили вусмерть
57 Torquader
 
16.10.13
01:01
(56) Ставишь pdf-принтер и печатаешь - то есть он не напечатать не может - только нужно правильно настраивать, чтобы имя файла присваивалось одно и то же.
Потом этот файл можно "отправлять" на реальный принтер.
58 Злопчинский
 
16.10.13
01:11
(57) подтверждение того, что пдф напечатался на реальном принтере...?
59 vcv
 
16.10.13
06:20
(56) Отключи в свойствах принтера "использование очереди печати" и будет тебе ожидание успеха/ошибки. Осталось только проверить, напечаталось или нет. Но тут, думаю, smaharbA "Великий и Ужасный" :) поможет.
60 VladZ
 
16.10.13
06:44
smaharbA не перестает удивлять.
Проблемы невозможно решaть нa том же уровне компетентности, нa котором они возникaют. Альберт Эйнштейн