В истории буфера обмена копится мусор от операций turboconf

Добавил: tormozit, 23 марта 2021 19:59, обновлено: 23 марта 2021 20:01

Раздел: Баги


Понимаю, почему в turboconf используется буфер обмена как ячейка для чтения/записи текста в окна UIAutomation. Но многие пользователи и я в их числе использует ведение истории буфера обмена для повторного использования клипов. После обновления где то с начала февраля к сожалению даже всякие защитные меры писателей истории буфера не спасают от регистрации мусора от турбоконфа в этой истории.

Предлагаю описать тут способы, которыми turboconf изменяет содержимое буфера обмена. Попробуем найти оптимальное решение, включая возможную адаптацию представителя второй стороны - ClipAngel.


К списку тем

Комментарии

bolsun
23 марта 2021 20:15: #1

Добавить TurboConf в исключения, не помогает?


tormozit
23 марта 2021 20:14: #2

Так отправляет же не только turboconf, но и сам процесс конфигуратора после получения команды CTRL+C от turboconfа.


tormozit
23 марта 2021 20:19: #3

К тому же у буфера обмена нет атрибута "Процесс-источник" к сожалению. Поэтому программы для ведения истории считают отправителем клипа активное окно. А оно уже может измениться в момент обработки события обновления буфера обмена подписантом. Поэтому 100% определять отправителя клипа невозможно. Особенно в случае с турбоконфом который свои окна быстро скрывает после завершения команды.


bolsun
23 марта 2021 20:21: #4

(2) tormozit, CTRL+C для получения данных не используется для платформы >= 8.3.8. Раньше да только через буфер получались данные.


tormozit
23 марта 2021 20:24: #5

Если в буфер помещает непосредственно turboconf, то можно ставить специальный флаг типа "не добавлять в историю". Это неофициальный стандарт среди менеджеров буфера обмена . Подробнее тут http://www.clipboardextender.com/developing-clipboard-aware-programs-for-windows/ignoring-clipboard-updates-with-the-cf_clipboard_viewer_ignore-clipboard-format


tormozit
23 марта 2021 20:27: #6

У меня чаще всего в историю попадает список методов модуля, т.к. я вызываю скрипт "Процедуры и функции". Я думал ты как раз через буфер обмена из штатного окна получаешь список. Раз ты получаешь оттуда текст напрямую, то непонятно почему он в буфер обмена попадает.


bolsun
23 марта 2021 20:27: #7

(6) tormozit, согласен, не везде через UIAutomation, в таких списках через буфер.


bolsun
23 марта 2021 20:28: #8

(5) tormozit, у тебя же на C# ClipAngel, ты используешь этот флаг при вставке?


bolsun
23 марта 2021 20:30: #9

Опять же как это поможет при Ctrl+C, там же 1С помещает в буфер и флага не будет никакого.


tormozit
23 марта 2021 20:32: #10

(8) bolsun, при вставке флаг не использую, т.к. я не делаю временного изменения содержимого буфера. А при захвате я его проверяю.


tormozit
23 марта 2021 20:37: #11

(7) bolsun, насколько сложно будет избавиться от использования буфера обмена для чтения текста из окон конфигуратора хотя бы в этом месте?


bolsun
23 марта 2021 20:40: #12

(11) tormozit, кроме как через буфер список не получить. Тут только типа какого-то костыля можно сделать.
Обычно сразу после копирования в буфер, идет восстановление буфера предыдущим значением.
Может удалять эти 2 операции если они идут вместе.


bolsun
23 марта 2021 20:55: #13

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


tormozit
24 марта 2021 10:54: #14

Предлагаю следующую систему сигнализации. Перед изменением текстового содержимого буфера обмена устанавливай в буфер обмена единственный формат с именем "ClipboardTempChange" и текстовым значением "Begin.<PID>" c ID процесса окна, которое будет слать временные данные в буфер. При восстановлении содержимого буфера обмена вместе с установкой туда оригинальных форматов добавляй формат с именем "ClipboardTempChange" и текстовым значением "End.<PID>" c ID процесса окна, которое завершило слать временные данные в буфер.


tormozit
24 марта 2021 10:42: #15

(12) bolsun, у тебя большие паузы бывают (более 400мс) между этими изменениями буфера. Такие вполне может делать и намеренно человек, который уверен, что все сохранилось в истории. Поэтому просто всегда удалять предыдущий клип тут будет нехорошо.


bolsun
24 марта 2021 11:43: #16

(14) tormozit, не знаю даже, работа с буфером и так нестабильна, приходится делать задержки, даже что бы одно значение установить, а тут придется на 2 операции больше делать.


tormozit
24 марта 2021 11:49: #17

(16) bolsun, на 1 обновление буфера больше, а не на 2. Согласен, что лишнее изменение буфера обмена - относительно высокая плата за такое исправление. Тогда предлагаю начать с добавления только второго сигнала -

При восстановлении содержимого буфера обмена вместе с установкой туда оригинальных форматов добавляй формат с именем "ClipboardTempChange" и текстовым значением "End.<PID>" c ID процесса окна, которое завершило слать временные данные в буфер.


bolsun
24 марта 2021 12:25: #18

(17) tormozit, флаг добавить можно, но что даст ID процесса? Ведь копирований при выполнении скрипта может быть несколько. Как понять какие отменять, а какие нет. Причем есть скрипты, которые по времени могут занимать достаточно продолжительное время.


bolsun
24 марта 2021 12:26: #19

"Clipboard Viewer Ignore" я попробовал добавить, вроде работает. Твоя программа не регистрирует такие изменения буфера.


tormozit
24 марта 2021 12:45: #20

(18) bolsun, в буфер обмена могут писать разные процессы. Будет нехорошо удалять клип от чужого процесса, который успел попасть между помещением тобой в буфер временного клипа и его восстановлением тобой.
Про то, что обновлений буфера (помимо восстановления) с твоей стороны может быть несколько для одной команды пользователя, ты впервые сообщаешь. Поэтому еще придется передавать момент начала с точностью до милисекунд. Теперь получается так -

При восстановлении содержимого буфера обмена вместе с установкой туда оригинальных форматов добавляй формат с именем "RemoveClipsFromHistory" и текстовым значением JSON:
PID=<PID>
TimeStart=<TimeBeginWithMiliseconds>
TimeEnd=<TimeEndWithMiliseconds>
где TimeStart - момент времени непосредственно перед отправкой в окно 1С первой команды CTRL+C из серии, а TimeEnd - момент времени сразу после считывания помещенного окном 1С текста в буфер после последней команды серии.


tormozit
24 марта 2021 12:39: #21

(19) bolsun, Так вроде уже много раз мы установили, что ты отправляешь в окно 1С CTRL+C и уже непосредственно оно отправляет данные в буфер обмена. Там ты не сможешь повлиять на установленные форматы. Их состав полностью определяет процесс конфигуратора.


bolsun
24 марта 2021 13:49: #22

(20) tormozit, слишком сложно и также без гарантированного результата из-за задержек. Что если я нажал Ctrl+C и через 100 мс, сразу запустил скрипт, который тоже нажал Ctrl+C.

Скрипты также пишут пользователи для себя, сколько раз, как, что и в каком окне (процессе) они там будут копировать никому не известно.


bolsun
24 марта 2021 13:53: #23

ИМХО просто отменять предыдущую вставку (после получения CF_CLIPBOARD_VIEWER_IGNORE от ТК), если время между ними в пределах какого-то небольшого интервала (200-300 мс). Во время выполнения скриптов, я блокирую ввод. Поэтому вероятность, что какие-то полезные данные будут скопированы пользователем в это время - минимальная.


bolsun
24 марта 2021 13:53: #24

Настройку можно сделать опциональной во вьювере.


tormozit
24 марта 2021 14:20: #25

(22) bolsun, видимо я просто чего то не знаю или не достаточно подробно описал.
Ты запускаешь скрипт по команде пользователя и сразу блокируешь ввод в окне конфигуратора. В какой то момент в скрипте идет отправка первой команды CTRL+C в конфигуратор. Вот перед ней нужно зафиксировать отметку времени. Дальше скрипт делает много всего и с буфером обмена в том числе, но ввод пользовательских команд заблокирован. В конце скрипт перед восстановлением буфера обмена и разблокировкой ввода пользователя также фиксирует отметку времени. Затем он восстанавливает содержимое буфера обмена и при этом добавляет новый формат с данными о периоде замусоривания буфера обмена. Мне схема кажется простой и понятной и достаточно надежной. Дополнительных обновлений буфера обмена не вызывает. Сложных алгоритмов не добавляет. Твоя программа будет предоставлять все нужные данные для наблюдателей за буфером, чтобы они могли убрать мусор из своей истории.

По поводу пользовательских скриптов - ну тут конечно можно нагородить что угодно и сломать что угодно. Поэтому принимать их в расчет не нужно, чтобы не добавлять 10-кратной сложности ради 10% случаев у 10% пользователей.


tormozit
24 марта 2021 14:25: #26

(23) bolsun, Использовать флаг CF_CLIPBOARD_VIEWER_IGNORE для удаления создаваемых твоей программой мусорных клипов - нехорошо, ведь этот флаг как я объяснял ранее является неофициальным стандартом и взводится многими программами, которые имеют другую логику работы и например там вредно будет удалять предыдущий клип. Если делать самый простой вариант, то все равно нужно свой флаг делать - например "RemoveLastClipFromHistory" и очень желательно PID все равно предоставлять, т.к. юзер мог переключиться на другое приложение, пока твой скрипт работал и там поместить что то полезное в буфер обмена.


bolsun
24 марта 2021 15:06: #27

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


tormozit
24 марта 2021 15:11: #28

(27) bolsun, если все так сложно, то значит просто бери на заметку. Как будешь что то связанное править, может и этот сложный механизм сделаешь. А пока тогда остановимся на простейшем варианте (26)


bolsun
24 марта 2021 15:28: #29

(28) tormozit, тут еще нужно подумать хорошенько.

RemoveLastClipFromHistory - не очень хорошо, а если копирования по какой-то причине не было, что будет удалено?


bolsun
24 марта 2021 15:28: #30

или интервал будет учитываться?


bolsun
24 марта 2021 15:38: #31

Предлагаю попробовать флаг сделать 'RemoveClipsFromHistory', а значение которого - период в ms. Я сам могу тогда задавать интервал за который удалить.


bolsun
24 марта 2021 15:39: #32

Можешь сделать мне тестовую сборку с этим флагом? Я попробую как это работает.


tormozit
24 марта 2021 15:49: #33

(31) bolsun, период задавать не очень хорошо, т.к. я могу обработать это событие тоже не сразу, например из-за того что буфер не сразу разблокируется (такое бывает). Поэтому желательно все таки иметь абсолютные отметки времени конца и начала.


bolsun
24 марта 2021 15:52: #34

(33) tormozit, ну давай значит в том формате

PID=<PID>
TimeStart=<TimeBeginWithMiliseconds>
TimeEnd=<TimeEndWithMiliseconds>

если PID = 0 то значит удалять от всех процессов за этот период.


bolsun
24 марта 2021 15:54: #35

и еще уточни время локальное или UTC и в каком формате.


tormozit
24 марта 2021 16:04: #36

(35) bolsun, предлагаю взять локальное время по формату из примера

string format = "dd/MM/yyyy HH:mm:ss.ff";
string str = DateTime.Now.ToString(format, CultureInfo.InvariantCulture);
DateTime date = DateTime.ParseExact(str, format, CultureInfo.InvariantCulture);
string str1 = date.ToString(format, CultureInfo.InvariantCulture);

bolsun
24 марта 2021 16:08: #37

(36) tormozit, ок, жду тогда сборку.


tormozit
24 марта 2021 18:39: #38

Готово. Формат буфера назвал - RemoveTempClipsFromHistory. Сериализацию все таки сделал через JSON формат - и тебе и мне меньше забот по сериализации/десериализации.
Рекомендую добавить в проект пакет Newtonsoft.Json (лицензия MIT). Тогда сформировать транспортную строку будет очень просто - пример

        public struct removeClipsFilter
        {
            public int PID;
            public DateTime TimeStart;
            public DateTime TimeEnd;
        }
				...
                removeClipsFilter removeClipsFilter = new removeClipsFilter
                {
                    PID = 54635
                    TimeStart = DateTime.Now.AddMilliseconds(-1000),
                    TimeEnd = DateTime.Now
                };
                dataString = JsonConvert.SerializeObject(removeClipsFilter);

ClipAngel 1.95.zip


bolsun
24 марта 2021 18:41: #39

(38) tormozit, посмотрю. Конечно я использую Newtonsoft.Json. Все сишарперы его используют ))


bolsun
24 марта 2021 18:43: #40

посмотрел ради интереса Newtonsoft.Json - 936 000 000 установок ))


bolsun
24 марта 2021 19:01: #41

(38) tormozit, PID = 0 поддерживается?


tormozit
24 марта 2021 19:02: #42

(41) bolsun, да


bolsun
24 марта 2021 19:05: #43

(41) bolsun, тогда что-то не работает.
Как у тебя выглядит RegisterClipboardFormat? какая строка?


bolsun
24 марта 2021 19:06: #44

Имя формата 'RemoveTempClipsFromHistory' ?


tormozit
24 марта 2021 19:06: #45

(44) bolsun, у меня ее нет. Это должен звать создатель клипов этого формата.


bolsun
24 марта 2021 19:07: #46

(45) tormozit, я регистрирую "RemoveTempClipsFromHistory"


bolsun
24 марта 2021 19:07: #47

но ничего не удаляется,
"Clipboard Viewer Ignore" работает


bolsun
24 марта 2021 19:09: #48

Ты можешь вывести алерт, если есть RemoveTempClipsFromHistory и параметры?


tormozit
24 марта 2021 19:10: #49

(48) bolsun, поставь CLCL - там удобно смотреть текущие форматы в буфере Clip_222181.png


tormozit
24 марта 2021 19:12: #50

Виноват. Отправил тебе из релизной папки сброку. А тестил на дебаге. Сейчас исправлюсь.


tormozit
24 марта 2021 19:16: #51

bolsun
24 марта 2021 19:20: #52

del


bolsun
24 марта 2021 19:21: #53

(51) tormozit, 2021-03-24_211912.png


tormozit
24 марта 2021 19:22: #54

(53) bolsun, Может ты null вместо 0 передал в PID?


bolsun
24 марта 2021 19:28: #55

(54) tormozit, мой косяк, не то передал. Но падать все равно не нужно )


tormozit
24 марта 2021 19:30: #56

(55) bolsun, ну если бы я не показал ошибку, то мы тут еще бы 3 часа разбирались. Поэтому я за "здоровое" падение.


bolsun
24 марта 2021 19:32: #57

Теперь удаляет, но есть проблема. Не удаляет тот текст, который приходит при восстановлении буфера.
Если добавить флаг ClipboardIgnoreFormatString, то игнорирует текст, но не удаляет предыдущие.


tormozit
24 марта 2021 19:36: #58

А зачем удалять текст, который приходит при восстановлении буфера? Об этом речи не шло. Можешь на примере текстом пояснить?


bolsun
24 марта 2021 19:51: #59

(58) tormozit, ну да, согласен, похоже не нужно.


bolsun
02 апреля 2021 16:25: #60

bolsun изменил статус на Закрыто


tormozit
13 апреля 2021 23:12: #61

При захвате мусорных клипов в локальном сеансе из дистанционного (например RDP), время локальное и дистанционное может сильно отличаться даже в одном часовом поясе. Поэтому в структуре, которую ты кидаешь в буфер для удаления мусорных клипов прошу добавить CurrentTime (текущее время), чтобы я мог хоть как то сориентироваться в смещении времени. А PID в связи с этим можно удалить (только сообщи мне, чтобы я у себя продублировал).


bolsun
14 апреля 2021 07:53: #62

bolsun изменил статус на Открыто


bolsun
22 апреля 2021 11:46: #63

(61) tormozit, CurrentTime получается будет совпадать с TimeEnd


tormozit
22 апреля 2021 12:25: #64

Ты всегда сразу после последнего мусорного клипа отправляешь этот служебный клип? Если да, то я сделаю расчет смещения времени через TimeEnd.


bolsun
22 апреля 2021 12:49: #65

(64) tormozit, я при каждой вставке, которую нужно исключить добавляю эти служебные данные.


tormozit
25 апреля 2021 15:45: #66

Да. TimeEnd оказалось вполне достаточно чтобы смещение считать.


bolsun
25 апреля 2021 16:06: #67

bolsun изменил статус на Закрыто


TurboConf

Расширение возможностей

Конфигуратора 1С

Скачать

Бесплатный пробный период 14 дней